/*------------------------------------------------------------------------------ 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.34 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/storage/src/WebStorageClient.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 #include #include #include #include #include #include "LiveSupport/Core/Md5.h" #include "LiveSupport/Core/XmlRpcCommunicationException.h" #include "LiveSupport/Core/XmlRpcMethodFaultException.h" #include "LiveSupport/Core/XmlRpcMethodResponseException.h" #include "LiveSupport/Core/XmlRpcInvalidArgumentException.h" #include "LiveSupport/Core/XmlRpcIOException.h" #include "WebStorageClient.h" using namespace boost::posix_time; using namespace XmlRpc; using namespace LiveSupport::Core; using namespace LiveSupport::Storage; /* =================================================== local data structures */ /* ================================================ local constants & macros */ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ configuration file constants */ /*------------------------------------------------------------------------------ * The name of the config element for this class *----------------------------------------------------------------------------*/ const std::string WebStorageClient::configElementNameStr = "webStorage"; /*------------------------------------------------------------------------------ * The name of the config element attribute for the temp files *----------------------------------------------------------------------------*/ static const std::string localTempStorageAttrName = "tempFiles"; /*------------------------------------------------------------------------------ * The name of the config child element for the storage server location *----------------------------------------------------------------------------*/ static const std::string locationConfigElementName = "location"; /*------------------------------------------------------------------------------ * The name of the config element attribute for the storage server name *----------------------------------------------------------------------------*/ static const std::string locationServerAttrName = "server"; /*------------------------------------------------------------------------------ * The name of the config element attribute for the storage server port *----------------------------------------------------------------------------*/ static const std::string locationPortAttrName = "port"; /*------------------------------------------------------------------------------ * The name of the config element attribute for the storage server php page *----------------------------------------------------------------------------*/ static const std::string locationPathAttrName = "path"; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ constants for the SMIL file */ /*------------------------------------------------------------------------------ * 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"; /*------------------------------------------------------------------------------ * 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"; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ storage server constants: error reports */ /*------------------------------------------------------------------------------ * The name of the error code parameter in the returned struct *----------------------------------------------------------------------------*/ static const std::string errorCodeParamName = "faultCode"; /*------------------------------------------------------------------------------ * The name of the error message parameter in the returned struct *----------------------------------------------------------------------------*/ static const std::string errorMessageParamName = "faultString"; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ storage server constants: resetStorage */ /*------------------------------------------------------------------------------ * The name of the reset storage method on the storage server *----------------------------------------------------------------------------*/ static const std::string resetStorageMethodName = "locstor.resetStorage"; /*------------------------------------------------------------------------------ * The name of the audio clips result parameter returned by the method *----------------------------------------------------------------------------*/ static const std::string resetStorageAudioClipResultParamName = "audioclips"; /*------------------------------------------------------------------------------ * The name of the playlists result parameter returned by the method *----------------------------------------------------------------------------*/ static const std::string resetStoragePlaylistResultParamName = "playlists"; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ storage server constants: search */ /*------------------------------------------------------------------------------ * The name of the search method on the storage server *----------------------------------------------------------------------------*/ static const std::string searchMethodName = "locstor.searchMetadata"; /*------------------------------------------------------------------------------ * The name of the session ID parameter in the input structure *----------------------------------------------------------------------------*/ static const std::string searchSessionIdParamName = "sessid"; /*------------------------------------------------------------------------------ * The name of the search criteria parameter in the input structure *----------------------------------------------------------------------------*/ static const std::string searchCriteriaParamName = "criteria"; /*------------------------------------------------------------------------------ * The name of the audio clips result parameter returned by the method *----------------------------------------------------------------------------*/ static const std::string searchAudioClipResultParamName = "audioClipResults"; /*------------------------------------------------------------------------------ * The name of the playlists result parameter returned by the method *----------------------------------------------------------------------------*/ static const std::string searchPlaylistResultParamName = "playlistResults"; /*------------------------------------------------------------------------------ * The name of the audio clip count parameter returned by the method *----------------------------------------------------------------------------*/ static const std::string searchAudioClipCountParamName = "audioClipCnt"; /*------------------------------------------------------------------------------ * The name of the playlist count parameter returned by the method *----------------------------------------------------------------------------*/ static const std::string searchPlaylistCountParamName = "playlistCnt"; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ playlist methods */ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ storage server constants: createPlaylist */ /*------------------------------------------------------------------------------ * The name of the create playlist method on the storage server *----------------------------------------------------------------------------*/ static const std::string createPlaylistMethodName = "locstor.createPlaylist"; /*------------------------------------------------------------------------------ * The name of the session ID parameter in the input structure *----------------------------------------------------------------------------*/ static const std::string createPlaylistSessionIdParamName = "sessid"; /*------------------------------------------------------------------------------ * The name of the playlist unique ID parameter in the input structure *----------------------------------------------------------------------------*/ static const std::string createPlaylistPlaylistIdParamName = "plid"; /*------------------------------------------------------------------------------ * The name of the result parameter returned by the method *----------------------------------------------------------------------------*/ static const std::string createPlaylistResultParamName = "plid"; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ storage server constants: existsPlaylist */ /*------------------------------------------------------------------------------ * The name of the exists playlist method on the storage server *----------------------------------------------------------------------------*/ static const std::string existsPlaylistMethodName = "locstor.existsPlaylist"; /*------------------------------------------------------------------------------ * The name of the session ID parameter in the input structure *----------------------------------------------------------------------------*/ static const std::string existsPlaylistSessionIdParamName = "sessid"; /*------------------------------------------------------------------------------ * The name of the audio clip unique ID parameter in the input structure *----------------------------------------------------------------------------*/ static const std::string existsPlaylistPlaylistIdParamName = "plid"; /*------------------------------------------------------------------------------ * The name of the result parameter returned by the method *----------------------------------------------------------------------------*/ static const std::string existsPlaylistResultParamName = "exists"; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ storage server constants: getPlaylist */ /*------------------------------------------------------------------------------ * The name of the opening 'get playlist' method on the storage server *----------------------------------------------------------------------------*/ static const std::string getPlaylistOpenMethodName = "locstor.accessPlaylist"; /*------------------------------------------------------------------------------ * The name of the closing 'get playlist' method on the storage server *----------------------------------------------------------------------------*/ static const std::string getPlaylistCloseMethodName = "locstor.releasePlaylist"; /*------------------------------------------------------------------------------ * The name of the session ID parameter in the input structure *----------------------------------------------------------------------------*/ static const std::string getPlaylistSessionIdParamName = "sessid"; /*------------------------------------------------------------------------------ * The name of the playlist unique ID parameter in the input structure *----------------------------------------------------------------------------*/ static const std::string getPlaylistPlaylistIdParamName = "plid"; /*------------------------------------------------------------------------------ * The name of the result URL parameter returned by the method *----------------------------------------------------------------------------*/ static const std::string getPlaylistUrlParamName = "url"; /*------------------------------------------------------------------------------ * The name of the token parameter returned (for open) or input (for close) *----------------------------------------------------------------------------*/ static const std::string getPlaylistTokenParamName = "token"; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ storage server constants: editPlaylist */ /*------------------------------------------------------------------------------ * The name of the 'edit playlist' method on the storage server *----------------------------------------------------------------------------*/ static const std::string editPlaylistMethodName = "locstor.editPlaylist"; /*------------------------------------------------------------------------------ * The name of the session ID parameter in the input structure *----------------------------------------------------------------------------*/ static const std::string editPlaylistSessionIdParamName = "sessid"; /*------------------------------------------------------------------------------ * The name of the playlist unique ID parameter in the input structure *----------------------------------------------------------------------------*/ static const std::string editPlaylistPlaylistIdParamName = "plid"; /*------------------------------------------------------------------------------ * The name of the result URL parameter returned by the method *----------------------------------------------------------------------------*/ static const std::string editPlaylistUrlParamName = "url"; /*------------------------------------------------------------------------------ * The name of the token parameter returned by the method *----------------------------------------------------------------------------*/ static const std::string editPlaylistTokenParamName = "token"; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ storage server constants: savePlaylist */ /*------------------------------------------------------------------------------ * XML header string *----------------------------------------------------------------------------*/ static const Glib::ustring xmlHeaderString = ""; /*------------------------------------------------------------------------------ * The name of the 'save playlist' method on the storage server *----------------------------------------------------------------------------*/ static const std::string savePlaylistMethodName = "locstor.savePlaylist"; /*------------------------------------------------------------------------------ * The name of the session ID parameter in the input structure *----------------------------------------------------------------------------*/ static const std::string savePlaylistSessionIdParamName = "sessid"; /*------------------------------------------------------------------------------ * The name of the token parameter in the input structure *----------------------------------------------------------------------------*/ static const std::string savePlaylistTokenParamName = "token"; /*------------------------------------------------------------------------------ * The name of the new playlist parameter in the input structure *----------------------------------------------------------------------------*/ static const std::string savePlaylistNewPlaylistParamName = "newPlaylist"; /*------------------------------------------------------------------------------ * The name of the result parameter returned by the method *----------------------------------------------------------------------------*/ static const std::string savePlaylistResultParamName = "plid"; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ storage server constants: deletePlaylist */ /*------------------------------------------------------------------------------ * The name of the delete playlist method on the storage server *----------------------------------------------------------------------------*/ static const std::string deletePlaylistMethodName = "locstor.deletePlaylist"; /*------------------------------------------------------------------------------ * The name of the session ID parameter in the input structure *----------------------------------------------------------------------------*/ static const std::string deletePlaylistSessionIdParamName = "sessid"; /*------------------------------------------------------------------------------ * The name of the playlist unique ID parameter in the input structure *----------------------------------------------------------------------------*/ static const std::string deletePlaylistPlaylistIdParamName = "plid"; /*------------------------------------------------------------------------------ * The name of the result parameter returned by the method *----------------------------------------------------------------------------*/ static const std::string deletePlaylistResultParamName = "status"; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ audio clip methods */ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ storage server constants: existsAudioClip */ /*------------------------------------------------------------------------------ * The name of the exists audio clip method on the storage server *----------------------------------------------------------------------------*/ static const std::string existsAudioClipMethodName = "locstor.existsAudioClip"; /*------------------------------------------------------------------------------ * The name of the session ID parameter in the input structure *----------------------------------------------------------------------------*/ static const std::string existsAudioClipSessionIdParamName = "sessid"; /*------------------------------------------------------------------------------ * The name of the audio clip unique ID parameter in the input structure *----------------------------------------------------------------------------*/ static const std::string existsAudioClipAudioClipIdParamName = "gunid"; /*------------------------------------------------------------------------------ * The name of the result parameter returned by the method *----------------------------------------------------------------------------*/ static const std::string existsAudioClipResultParamName = "exists"; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ storage server constants: getAudioClip */ /*------------------------------------------------------------------------------ * The name of the opening 'get audio clip' method on the storage server *----------------------------------------------------------------------------*/ static const std::string getAudioClipOpenMethodName = "locstor.downloadMetadataOpen"; /*------------------------------------------------------------------------------ * The name of the closing 'get audio clip' method on the storage server *----------------------------------------------------------------------------*/ static const std::string getAudioClipCloseMethodName = "locstor.downloadMetadataClose"; /*------------------------------------------------------------------------------ * The name of the session ID parameter in the input structure *----------------------------------------------------------------------------*/ static const std::string getAudioClipSessionIdParamName = "sessid"; /*------------------------------------------------------------------------------ * The name of the audio clip unique ID parameter in the input structure *----------------------------------------------------------------------------*/ static const std::string getAudioClipAudioClipIdParamName = "gunid"; /*------------------------------------------------------------------------------ * The name of the result URL parameter returned by the method *----------------------------------------------------------------------------*/ static const std::string getAudioClipUrlParamName = "url"; /*------------------------------------------------------------------------------ * The name of the token parameter returned (for open) or input (for close) *----------------------------------------------------------------------------*/ static const std::string getAudioClipTokenParamName = "token"; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ storage server constants: storeAudioClip */ /*------------------------------------------------------------------------------ * The name of the opening 'store audio clip' method on the storage server *----------------------------------------------------------------------------*/ static const std::string storeAudioClipOpenMethodName = "locstor.storeAudioClipOpen"; /*------------------------------------------------------------------------------ * The name of the closing 'store audio clip' method on the storage server *----------------------------------------------------------------------------*/ static const std::string storeAudioClipCloseMethodName = "locstor.storeAudioClipClose"; /*------------------------------------------------------------------------------ * The name of the session ID parameter in the input structure *----------------------------------------------------------------------------*/ static const std::string storeAudioClipSessionIdParamName = "sessid"; /*------------------------------------------------------------------------------ * The name of the audio clip unique ID parameter for both 'open' and 'close' *----------------------------------------------------------------------------*/ static const std::string storeAudioClipAudioClipIdParamName = "gunid"; /*------------------------------------------------------------------------------ * The name of the metadata file name parameter in the input structure *----------------------------------------------------------------------------*/ static const std::string storeAudioClipMetadataParamName = "metadata"; /*------------------------------------------------------------------------------ * The name of the binary file name parameter in the input structure *----------------------------------------------------------------------------*/ static const std::string storeAudioClipFileNameParamName = "fname"; /*------------------------------------------------------------------------------ * The name of the checksum of the binary file name in the input structure *----------------------------------------------------------------------------*/ static const std::string storeAudioClipChecksumParamName = "chsum"; /*------------------------------------------------------------------------------ * The name of the URL parameter returned by the 'open' method *----------------------------------------------------------------------------*/ static const std::string storeAudioClipUrlParamName = "url"; /*------------------------------------------------------------------------------ * The name of the token parameter for both 'open' and 'close' methods *----------------------------------------------------------------------------*/ static const std::string storeAudioClipTokenParamName = "token"; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ storage server constants: acquireAudioClip */ /*------------------------------------------------------------------------------ * The name of the acquire audio clip method on the storage server *----------------------------------------------------------------------------*/ static const std::string acquireAudioClipMethodName = "locstor.accessRawAudioData"; /*------------------------------------------------------------------------------ * The name of the session ID parameter in the input structure *----------------------------------------------------------------------------*/ static const std::string acquireAudioClipSessionIdParamName = "sessid"; /*------------------------------------------------------------------------------ * The name of the audio clip unique ID parameter in the input structure *----------------------------------------------------------------------------*/ static const std::string acquireAudioClipAudioClipIdParamName = "gunid"; /*------------------------------------------------------------------------------ * The name of the result URL parameter returned by the method *----------------------------------------------------------------------------*/ static const std::string acquireAudioClipUrlParamName = "url"; /*------------------------------------------------------------------------------ * The name of the token parameter returned by the method *----------------------------------------------------------------------------*/ static const std::string acquireAudioClipTokenParamName = "token"; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ storage server constants: releaseAudioClip */ /*------------------------------------------------------------------------------ * The name of the release audio clip method on the storage server *----------------------------------------------------------------------------*/ static const std::string releaseAudioClipMethodName = "locstor.releaseRawAudioData"; /*------------------------------------------------------------------------------ * The name of the session ID parameter in the input structure *----------------------------------------------------------------------------*/ static const std::string releaseAudioClipSessionIdParamName = "sessid"; /*------------------------------------------------------------------------------ * The name of the token parameter in the input structure *----------------------------------------------------------------------------*/ static const std::string releaseAudioClipTokenParamName = "token"; /*------------------------------------------------------------------------------ * The name of the result parameter returned by the method *----------------------------------------------------------------------------*/ static const std::string releaseAudioClipResultParamName = "status"; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ storage server constants: deleteAudioClip */ /*------------------------------------------------------------------------------ * The name of the delete audio clip method on the storage server *----------------------------------------------------------------------------*/ static const std::string deleteAudioClipMethodName = "locstor.deleteAudioClip"; /*------------------------------------------------------------------------------ * The name of the session ID parameter in the input structure *----------------------------------------------------------------------------*/ static const std::string deleteAudioClipSessionIdParamName = "sessid"; /*------------------------------------------------------------------------------ * The name of the audio clip unique ID parameter in the input structure *----------------------------------------------------------------------------*/ static const std::string deleteAudioClipAudioClipIdParamName = "gunid"; /*------------------------------------------------------------------------------ * The name of the result parameter returned by the method *----------------------------------------------------------------------------*/ static const std::string deleteAudioClipResultParamName = "status"; /* =============================================== local function prototypes */ /* ============================================================= module code */ /*------------------------------------------------------------------------------ * Configure the web storage client. *----------------------------------------------------------------------------*/ void WebStorageClient :: configure(const xmlpp::Element & element) throw (std::invalid_argument) { 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(); // read the storage server location xmlpp::Node::NodeList childNodes = element.get_children(locationConfigElementName); xmlpp::Node::NodeList::iterator it = childNodes.begin(); if (it == childNodes.end()) { std::string eMsg = "missing "; eMsg += locationConfigElementName; eMsg += " XML element"; throw std::invalid_argument(eMsg); } const xmlpp::Element * locationConfigElement = dynamic_cast (*it); if (!(attribute = locationConfigElement ->get_attribute(locationServerAttrName))) { std::string eMsg = "Missing attribute "; eMsg += locationServerAttrName; throw std::invalid_argument(eMsg); } storageServerName = attribute->get_value(); if (!(attribute = locationConfigElement ->get_attribute(locationPortAttrName))) { std::string eMsg = "Missing attribute "; eMsg += locationPortAttrName; throw std::invalid_argument(eMsg); } std::stringstream storageServerPortValue(attribute->get_value()); storageServerPortValue >> storageServerPort; if (!(attribute = locationConfigElement ->get_attribute(locationPathAttrName))) { std::string eMsg = "Missing attribute "; eMsg += locationPathAttrName; throw std::invalid_argument(eMsg); } storageServerPath = attribute->get_value(); ++it; if (it != childNodes.end()) { std::string eMsg = "more than one "; eMsg += locationConfigElementName; eMsg += " XML element"; throw std::invalid_argument(eMsg); } } /*------------------------------------------------------------------------------ * Create a new playlist. *----------------------------------------------------------------------------*/ Ptr::Ref WebStorageClient :: createPlaylist(Ptr::Ref sessionId) throw (Core::XmlRpcException) { XmlRpcValue parameters; XmlRpcValue result; XmlRpcClient xmlRpcClient(storageServerName.c_str(), storageServerPort, storageServerPath.c_str(), false); parameters.clear(); parameters[createPlaylistSessionIdParamName] = sessionId->getId(); result.clear(); if (!xmlRpcClient.execute(createPlaylistMethodName.c_str(), parameters, result)) { xmlRpcClient.close(); std::string eMsg = "cannot execute XML-RPC method '"; eMsg += createPlaylistMethodName; eMsg += "'"; throw XmlRpcCommunicationException(eMsg); } xmlRpcClient.close(); if (xmlRpcClient.isFault()) { std::stringstream eMsg; eMsg << "XML-RPC method '" << createPlaylistMethodName << "' returned error message:\n" << result; throw Core::XmlRpcMethodFaultException(eMsg.str()); } if (! result.hasMember(createPlaylistResultParamName) || result[createPlaylistResultParamName].getType() != XmlRpcValue::TypeString) { std::stringstream eMsg; eMsg << "XML-RPC method '" << createPlaylistMethodName << "' returned unexpected value:\n" << result; throw XmlRpcMethodResponseException(eMsg.str()); } Ptr::Ref newId(new UniqueId(std::string( result[createPlaylistResultParamName] ))); Ptr::Ref url, token; editPlaylistGetUrl(sessionId, newId, url, token); Ptr::Ref playlength(new time_duration(0,0,0,0)); Ptr::Ref playlist(new Playlist(newId, playlength)); playlist->setToken(token); editedPlaylists[newId->getId()] = std::make_pair(sessionId, playlist); savePlaylist(sessionId, playlist); token.reset(); playlist->setToken(token); return playlist->getId(); } /*------------------------------------------------------------------------------ * Tell if a playlist exists. *----------------------------------------------------------------------------*/ const bool WebStorageClient :: existsPlaylist(Ptr::Ref sessionId, Ptr::Ref id) const throw (Core::XmlRpcException) { XmlRpcValue parameters; XmlRpcValue result; XmlRpcClient xmlRpcClient(storageServerName.c_str(), storageServerPort, storageServerPath.c_str(), false); parameters.clear(); parameters[existsPlaylistSessionIdParamName] = sessionId->getId(); parameters[existsPlaylistPlaylistIdParamName] = std::string(*id); result.clear(); if (!xmlRpcClient.execute(existsPlaylistMethodName.c_str(), parameters, result)) { xmlRpcClient.close(); std::string eMsg = "cannot execute XML-RPC method '"; eMsg += existsPlaylistMethodName; eMsg += "'"; throw XmlRpcCommunicationException(eMsg); } xmlRpcClient.close(); if (xmlRpcClient.isFault()) { std::stringstream eMsg; eMsg << "XML-RPC method '" << existsPlaylistMethodName << "' returned error message:\n" << result; throw Core::XmlRpcMethodFaultException(eMsg.str()); } if (! result.hasMember(existsPlaylistResultParamName) || result[existsPlaylistResultParamName].getType() != XmlRpcValue::TypeBoolean) { std::stringstream eMsg; eMsg << "XML-RPC method '" << existsPlaylistMethodName << "' returned unexpected value:\n" << result; throw XmlRpcMethodResponseException(eMsg.str()); } return bool(result[existsPlaylistResultParamName]); } /*------------------------------------------------------------------------------ * Return a playlist to be displayed. *----------------------------------------------------------------------------*/ Ptr::Ref WebStorageClient :: getPlaylist(Ptr::Ref sessionId, Ptr::Ref id) const throw (Core::XmlRpcException) { EditedPlaylistsType::const_iterator editIt = editedPlaylists.find(id->getId()); if (editIt != editedPlaylists.end() // is being edited && (*editIt->second.first == *sessionId)) { // by us return editIt->second.second; } XmlRpcValue parameters; XmlRpcValue result; XmlRpcClient xmlRpcClient(storageServerName.c_str(), storageServerPort, storageServerPath.c_str(), false); parameters.clear(); parameters[getPlaylistSessionIdParamName] = sessionId->getId(); parameters[getPlaylistPlaylistIdParamName] = std::string(*id); result.clear(); if (!xmlRpcClient.execute(getPlaylistOpenMethodName.c_str(), parameters, result)) { xmlRpcClient.close(); std::string eMsg = "cannot execute XML-RPC method '"; eMsg += getPlaylistOpenMethodName; eMsg += "'"; throw XmlRpcCommunicationException(eMsg); } if (xmlRpcClient.isFault()) { std::stringstream eMsg; eMsg << "XML-RPC method '" << getPlaylistOpenMethodName << "' returned error message:\n" << result; throw Core::XmlRpcMethodFaultException(eMsg.str()); } if (! result.hasMember(getPlaylistUrlParamName) || result[getPlaylistUrlParamName].getType() != XmlRpcValue::TypeString || ! result.hasMember(getPlaylistTokenParamName) || result[getPlaylistTokenParamName].getType() != XmlRpcValue::TypeString) { std::stringstream eMsg; eMsg << "XML-RPC method '" << getPlaylistOpenMethodName << "' returned unexpected value:\n" << result; throw XmlRpcMethodResponseException(eMsg.str()); } const std::string url = result[getPlaylistUrlParamName]; const std::string token = result[getPlaylistTokenParamName]; Ptr::Ref playlist(new Playlist(id)); try { Ptr::Ref parser(new xmlpp::DomParser()); parser->parse_file(url); const xmlpp::Document * document = parser->get_document(); const xmlpp::Element * root = document->get_root_node(); playlist->configure(*root); } catch (std::invalid_argument &e) { throw XmlRpcMethodResponseException( "semantic error in playlist metafile"); } catch (xmlpp::exception &e) { throw XmlRpcMethodResponseException( "error parsing playlist metafile"); } parameters.clear(); parameters[getPlaylistSessionIdParamName] = sessionId->getId(); parameters[getPlaylistTokenParamName] = token; result.clear(); if (!xmlRpcClient.execute(getPlaylistCloseMethodName.c_str(), parameters, result)) { xmlRpcClient.close(); std::string eMsg = "cannot execute XML-RPC method '"; eMsg += getPlaylistCloseMethodName; eMsg += "'"; throw XmlRpcCommunicationException(eMsg); } xmlRpcClient.close(); if (xmlRpcClient.isFault()) { std::stringstream eMsg; eMsg << "XML-RPC method '" << getPlaylistCloseMethodName << "' returned error message:\n" << result; throw Core::XmlRpcMethodFaultException(eMsg.str()); } if (! result.hasMember(getPlaylistPlaylistIdParamName) || result[getPlaylistPlaylistIdParamName].getType() != XmlRpcValue::TypeString || std::string(result[getPlaylistPlaylistIdParamName]) != std::string(*id)) { std::stringstream eMsg; eMsg << "XML-RPC method '" << getPlaylistCloseMethodName << "' returned unexpected value:\n" << result; throw XmlRpcMethodResponseException(eMsg.str()); } return playlist; } /*------------------------------------------------------------------------------ * Return a playlist to be edited. *----------------------------------------------------------------------------*/ Ptr::Ref WebStorageClient :: editPlaylist(Ptr::Ref sessionId, Ptr::Ref id) throw (Core::XmlRpcException) { if (editedPlaylists.find(id->getId()) != editedPlaylists.end()) { throw XmlRpcInvalidArgumentException("playlist is already" " being edited"); } Ptr::Ref url, token; editPlaylistGetUrl(sessionId, id, url, token); Ptr::Ref playlist(new Playlist(id)); try { Ptr::Ref parser(new xmlpp::DomParser()); parser->parse_file(*url); const xmlpp::Document * document = parser->get_document(); const xmlpp::Element * root = document->get_root_node(); playlist->configure(*root); } catch (std::invalid_argument &e) { throw XmlRpcMethodResponseException( "semantic error in playlist metafile"); } catch (xmlpp::exception &e) { throw XmlRpcMethodResponseException( "error parsing playlist metafile"); } playlist->setToken(token); editedPlaylists[id->getId()] = std::make_pair(sessionId, playlist); return playlist; } void WebStorageClient :: editPlaylistGetUrl(Ptr::Ref sessionId, Ptr::Ref id, Ptr::Ref& url, Ptr::Ref& token) throw (Core::XmlRpcException) { XmlRpcValue parameters; XmlRpcValue result; XmlRpcClient xmlRpcClient(storageServerName.c_str(), storageServerPort, storageServerPath.c_str(), false); parameters.clear(); parameters[editPlaylistSessionIdParamName] = sessionId->getId(); parameters[editPlaylistPlaylistIdParamName] = std::string(*id); result.clear(); if (!xmlRpcClient.execute(editPlaylistMethodName.c_str(), parameters, result)) { xmlRpcClient.close(); std::string eMsg = "cannot execute XML-RPC method '"; eMsg += editPlaylistMethodName; eMsg += "'"; throw XmlRpcCommunicationException(eMsg); } xmlRpcClient.close(); if (xmlRpcClient.isFault()) { std::stringstream eMsg; eMsg << "XML-RPC method '" << editPlaylistMethodName << "' returned error message:\n" << result; throw Core::XmlRpcMethodFaultException(eMsg.str()); } if (! result.hasMember(editPlaylistUrlParamName) || result[editPlaylistUrlParamName].getType() != XmlRpcValue::TypeString || ! result.hasMember(editPlaylistTokenParamName) || result[editPlaylistTokenParamName].getType() != XmlRpcValue::TypeString) { std::stringstream eMsg; eMsg << "XML-RPC method '" << editPlaylistMethodName << "' returned unexpected value:\n" << result; throw XmlRpcMethodResponseException(eMsg.str()); } url.reset(new const std::string(result[getPlaylistUrlParamName])); token.reset(new const std::string(result[getPlaylistTokenParamName])); } /*------------------------------------------------------------------------------ * Save a playlist after editing. *----------------------------------------------------------------------------*/ void WebStorageClient :: savePlaylist(Ptr::Ref sessionId, Ptr::Ref playlist) throw (Core::XmlRpcException) { if (!playlist || !playlist->getToken()) { throw XmlRpcInvalidArgumentException("playlist has no token field"); } EditedPlaylistsType::iterator editIt = editedPlaylists.find(playlist->getId()->getId()); if ((editIt == editedPlaylists.end()) || *editIt->second.first != *sessionId) { throw XmlRpcInvalidArgumentException("savePlaylist() called without " "editPlaylist()"); } editedPlaylists.erase(editIt); XmlRpcValue parameters; XmlRpcValue result; XmlRpcClient xmlRpcClient(storageServerName.c_str(), storageServerPort, storageServerPath.c_str(), false); parameters.clear(); parameters[savePlaylistSessionIdParamName] = sessionId->getId(); parameters[savePlaylistTokenParamName] = *playlist->getToken(); parameters[savePlaylistNewPlaylistParamName] = std::string(xmlHeaderString + *playlist->getXmlString()); result.clear(); if (!xmlRpcClient.execute(savePlaylistMethodName.c_str(), parameters, result)) { xmlRpcClient.close(); std::string eMsg = "cannot execute XML-RPC method '"; eMsg += savePlaylistMethodName; eMsg += "'"; throw XmlRpcCommunicationException(eMsg); } xmlRpcClient.close(); if (xmlRpcClient.isFault()) { std::stringstream eMsg; eMsg << "XML-RPC method '" << savePlaylistMethodName << "' returned error message:\n" << result; throw Core::XmlRpcMethodFaultException(eMsg.str()); } if (! result.hasMember(savePlaylistResultParamName) || result[savePlaylistResultParamName].getType() != XmlRpcValue::TypeString || std::string(result[savePlaylistResultParamName]) != std::string(*playlist->getId())) { std::stringstream eMsg; eMsg << "XML-RPC method '" << savePlaylistMethodName << "' returned unexpected value:\n" << result; throw XmlRpcMethodResponseException(eMsg.str()); } Ptr::Ref nullpointer; playlist->setToken(nullpointer); } /*------------------------------------------------------------------------------ * Acquire resources for a playlist. *----------------------------------------------------------------------------*/ Ptr::Ref WebStorageClient :: acquirePlaylist(Ptr::Ref sessionId, Ptr::Ref id) const throw (Core::XmlRpcException) { Ptr::Ref oldPlaylist = getPlaylist(sessionId, id); Ptr::Ref playlength = 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 plElement = it->second; Ptr::Ref fadeInfo = plElement->getFadeInfo(); 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 = smilSeqNode->add_child(smilAudioClipNodeName); 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 throw XmlRpcInvalidArgumentException( "unexpected playlist element type " "(neither audio clip nor playlist)"); } } std::stringstream fileName; fileName << localTempStorage << std::string(*newPlaylist->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 WebStorageClient :: releasePlaylist(Ptr::Ref sessionId, Ptr::Ref playlist) const throw (Core::XmlRpcException) { if (! playlist->getUri()) { throw XmlRpcInvalidArgumentException("playlist URI not found"); } std::ifstream ifs(playlist->getUri()->substr(7).c_str()); if (!ifs) { // cut of "file://" ifs.close(); throw XmlRpcIOException("playlist temp file not found"); } ifs.close(); std::remove(playlist->getUri()->substr(7).c_str()); std::string eMsg = ""; Playlist::const_iterator it = playlist->begin(); while (it != playlist->end()) { Ptr::Ref plElement = it->second; if (plElement->getType() == PlaylistElement::AudioClipType) { try { releaseAudioClip(sessionId, it->second->getAudioClip()); } catch (XmlRpcException &e) { eMsg += e.what(); eMsg += "\n"; } ++it; } else if (plElement->getType() == PlaylistElement::PlaylistType) { try { releasePlaylist(sessionId, it->second->getPlaylist()); } catch (XmlRpcException &e) { eMsg += e.what(); eMsg += "\n"; } ++it; } else { // this should never happen eMsg += "unexpected playlist element type\n"; } } Ptr::Ref nullPointer; playlist->setUri(nullPointer); if (eMsg != "") { eMsg.insert(0, "some playlist elements could not be released:\n"); throw XmlRpcInvalidArgumentException(eMsg); } } /*------------------------------------------------------------------------------ * Delete a playlist. *----------------------------------------------------------------------------*/ void WebStorageClient :: deletePlaylist(Ptr::Ref sessionId, Ptr::Ref id) throw (Core::XmlRpcException) { XmlRpcValue parameters; XmlRpcValue result; XmlRpcClient xmlRpcClient(storageServerName.c_str(), storageServerPort, storageServerPath.c_str(), false); parameters.clear(); parameters[deletePlaylistSessionIdParamName] = sessionId->getId(); parameters[deletePlaylistPlaylistIdParamName] = std::string(*id); result.clear(); if (!xmlRpcClient.execute(deletePlaylistMethodName.c_str(), parameters, result)) { xmlRpcClient.close(); std::string eMsg = "cannot execute XML-RPC method '"; eMsg += deletePlaylistMethodName; eMsg += "'"; throw XmlRpcCommunicationException(eMsg); } xmlRpcClient.close(); if (xmlRpcClient.isFault()) { std::stringstream eMsg; eMsg << "XML-RPC method '" << deletePlaylistMethodName << "' returned error message:\n" << result; throw Core::XmlRpcMethodFaultException(eMsg.str()); } if (! result.hasMember(deletePlaylistResultParamName) || result[deletePlaylistResultParamName].getType() != XmlRpcValue::TypeBoolean) { std::stringstream eMsg; eMsg << "XML-RPC method '" << deletePlaylistMethodName << "' returned unexpected value:\n" << result; throw XmlRpcMethodResponseException(eMsg.str()); } if (! bool(result[deletePlaylistResultParamName])) { std::stringstream eMsg; eMsg << "XML-RPC method '" << deletePlaylistMethodName << "' returned 'false'"; throw XmlRpcMethodResponseException(eMsg.str()); } } /*------------------------------------------------------------------------------ * Tell if an audio clip exists. *----------------------------------------------------------------------------*/ const bool WebStorageClient :: existsAudioClip(Ptr::Ref sessionId, Ptr::Ref id) const throw (Core::XmlRpcException) { XmlRpcValue parameters; XmlRpcValue result; XmlRpcClient xmlRpcClient(storageServerName.c_str(), storageServerPort, storageServerPath.c_str(), false); parameters.clear(); parameters[existsAudioClipSessionIdParamName] = sessionId->getId(); parameters[existsAudioClipAudioClipIdParamName] = std::string(*id); result.clear(); if (!xmlRpcClient.execute(existsAudioClipMethodName.c_str(), parameters, result)) { xmlRpcClient.close(); std::string eMsg = "cannot execute XML-RPC method '"; eMsg += existsAudioClipMethodName; eMsg += "'"; throw XmlRpcCommunicationException(eMsg); } xmlRpcClient.close(); if (xmlRpcClient.isFault()) { std::stringstream eMsg; eMsg << "XML-RPC method '" << existsAudioClipMethodName << "' returned error message:\n" << result; throw Core::XmlRpcMethodFaultException(eMsg.str()); } if (! result.hasMember(existsAudioClipResultParamName) || result[existsAudioClipResultParamName].getType() != XmlRpcValue::TypeBoolean) { std::stringstream eMsg; eMsg << "XML-RPC method '" << existsAudioClipMethodName << "' returned unexpected value:\n" << result; throw XmlRpcMethodResponseException(eMsg.str()); } return bool(result[existsAudioClipResultParamName]); } /*------------------------------------------------------------------------------ * Retrieve an audio clip from the storage. *----------------------------------------------------------------------------*/ Ptr::Ref WebStorageClient :: getAudioClip(Ptr::Ref sessionId, Ptr::Ref id) const throw (Core::XmlRpcException) { XmlRpcValue parameters; XmlRpcValue result; XmlRpcClient xmlRpcClient(storageServerName.c_str(), storageServerPort, storageServerPath.c_str(), false); parameters.clear(); parameters[getAudioClipSessionIdParamName] = sessionId->getId(); parameters[getAudioClipAudioClipIdParamName] = std::string(*id); result.clear(); if (!xmlRpcClient.execute(getAudioClipOpenMethodName.c_str(), parameters, result)) { xmlRpcClient.close(); std::string eMsg = "cannot execute XML-RPC method '"; eMsg += getAudioClipOpenMethodName; eMsg += "'"; throw XmlRpcCommunicationException(eMsg); } if (xmlRpcClient.isFault()) { std::stringstream eMsg; eMsg << "XML-RPC method '" << getAudioClipOpenMethodName << "' returned error message:\n" << result; throw Core::XmlRpcMethodFaultException(eMsg.str()); } if (! result.hasMember(getAudioClipUrlParamName) || result[getAudioClipUrlParamName].getType() != XmlRpcValue::TypeString || ! result.hasMember(getAudioClipTokenParamName) || result[getAudioClipTokenParamName].getType() != XmlRpcValue::TypeString) { std::stringstream eMsg; eMsg << "XML-RPC method '" << getAudioClipOpenMethodName << "' returned unexpected value:\n" << result; throw XmlRpcMethodResponseException(eMsg.str()); } const std::string url = result[getAudioClipUrlParamName]; const std::string token = result[getAudioClipTokenParamName]; Ptr::Ref audioClip(new AudioClip(id)); try { Ptr::Ref parser(new xmlpp::DomParser()); parser->parse_file(url); const xmlpp::Document * document = parser->get_document(); const xmlpp::Element * root = document->get_root_node(); audioClip->configure(*root); } catch (std::invalid_argument &e) { std::string eMsg = "semantic error in audio clip metafile:\n"; eMsg += e.what(); throw XmlRpcMethodResponseException(eMsg); } catch (xmlpp::exception &e) { std::string eMsg = "error parsing audio clip metafile"; eMsg += e.what(); throw XmlRpcMethodResponseException(eMsg); } parameters.clear(); parameters[getAudioClipSessionIdParamName] = sessionId->getId(); parameters[getAudioClipTokenParamName] = token; result.clear(); if (!xmlRpcClient.execute(getAudioClipCloseMethodName.c_str(), parameters, result)) { xmlRpcClient.close(); std::string eMsg = "cannot execute XML-RPC method '"; eMsg += getAudioClipCloseMethodName; eMsg += "'"; throw XmlRpcCommunicationException(eMsg); } xmlRpcClient.close(); if (xmlRpcClient.isFault()) { std::stringstream eMsg; eMsg << "XML-RPC method '" << getAudioClipCloseMethodName << "' returned error message:\n" << result; throw Core::XmlRpcMethodFaultException(eMsg.str()); } if (! result.hasMember(getAudioClipAudioClipIdParamName) || result[getAudioClipAudioClipIdParamName].getType() != XmlRpcValue::TypeString || std::string(result[getAudioClipAudioClipIdParamName]) != std::string(*id)) { std::stringstream eMsg; eMsg << "XML-RPC method '" << getAudioClipCloseMethodName << "' returned unexpected value:\n" << result; throw XmlRpcMethodResponseException(eMsg.str()); } return audioClip; } /*------------------------------------------------------------------------------ * Upload an audio clip to the local storage. *----------------------------------------------------------------------------*/ void WebStorageClient :: storeAudioClip(Ptr::Ref sessionId, Ptr::Ref audioClip) throw (Core::XmlRpcException) { if (!audioClip || !audioClip->getUri()) { throw XmlRpcInvalidArgumentException( "binary audio clip file not found"); } // temporary hack; we will expect an absolute file name from getUri() // in the final version std::string binaryFileName = audioClip->getUri()->substr(5); std::ifstream ifs(binaryFileName.c_str()); if (!ifs) { ifs.close(); throw XmlRpcIOException("could not read audio clip"); } std::string md5string = Md5(ifs); ifs.close(); XmlRpcValue parameters; XmlRpcValue result; XmlRpcClient xmlRpcClient(storageServerName.c_str(), storageServerPort, storageServerPath.c_str(), false); parameters.clear(); parameters[storeAudioClipSessionIdParamName] = sessionId->getId(); if (audioClip->getId()) { parameters[storeAudioClipAudioClipIdParamName] = std::string(*audioClip->getId()); } parameters[storeAudioClipMetadataParamName] = std::string(*audioClip->getMetadataString()); parameters[storeAudioClipFileNameParamName] = std::string(*audioClip->getUri()); parameters[storeAudioClipChecksumParamName] = md5string; result.clear(); if (!xmlRpcClient.execute(storeAudioClipOpenMethodName.c_str(), parameters, result)) { xmlRpcClient.close(); std::string eMsg = "cannot execute XML-RPC method '"; eMsg += storeAudioClipOpenMethodName; eMsg += "'"; throw XmlRpcCommunicationException(eMsg); } if (xmlRpcClient.isFault()) { std::stringstream eMsg; eMsg << "XML-RPC method '" << storeAudioClipOpenMethodName << "' returned error message:\n" << result; throw Core::XmlRpcMethodFaultException(eMsg.str()); } if (! result.hasMember(storeAudioClipUrlParamName) || result[storeAudioClipUrlParamName].getType() != XmlRpcValue::TypeString || ! result.hasMember(storeAudioClipTokenParamName) || result[storeAudioClipTokenParamName].getType() != XmlRpcValue::TypeString) { std::stringstream eMsg; eMsg << "XML-RPC method '" << storeAudioClipOpenMethodName << "' returned unexpected value:\n" << result; throw XmlRpcMethodResponseException(eMsg.str()); } std::string url = std::string(result[storeAudioClipUrlParamName]); std::string token = std::string(result[storeAudioClipTokenParamName]); FILE* binaryFile = fopen(binaryFileName.c_str(), "rb"); if (!binaryFile) { throw XmlRpcIOException("Binary audio clip file not found."); } fseek(binaryFile, 0, SEEK_END); long binaryFileSize = ftell(binaryFile); rewind(binaryFile); CURL* handle = curl_easy_init(); if (!handle) { throw XmlRpcCommunicationException("Could not obtain curl handle."); } int status = curl_easy_setopt(handle, CURLOPT_READDATA, binaryFile); status |= curl_easy_setopt(handle, CURLOPT_INFILESIZE, binaryFileSize); // works for files of size up to 2 GB status |= curl_easy_setopt(handle, CURLOPT_PUT, 1); status |= curl_easy_setopt(handle, CURLOPT_URL, url.c_str()); // status |= curl_easy_setopt(handle, CURLOPT_HEADER, 1); // status |= curl_easy_setopt(handle, CURLOPT_ENCODING, "deflate"); if (status) { throw XmlRpcCommunicationException("Could not set curl options."); } status = curl_easy_perform(handle); if (status) { throw XmlRpcCommunicationException("Error uploading file."); } curl_easy_cleanup(handle); fclose(binaryFile); parameters.clear(); parameters[storeAudioClipSessionIdParamName] = sessionId->getId(); parameters[storeAudioClipTokenParamName] = token; result.clear(); if (!xmlRpcClient.execute(storeAudioClipCloseMethodName.c_str(), parameters, result)) { xmlRpcClient.close(); std::string eMsg = "cannot execute XML-RPC method '"; eMsg += storeAudioClipCloseMethodName; eMsg += "'"; throw XmlRpcCommunicationException(eMsg); } xmlRpcClient.close(); if (xmlRpcClient.isFault()) { std::stringstream eMsg; eMsg << "XML-RPC method '" << storeAudioClipCloseMethodName << "' returned error message:\n" << result; throw Core::XmlRpcMethodFaultException(eMsg.str()); } if (! result.hasMember(storeAudioClipAudioClipIdParamName) || result[storeAudioClipAudioClipIdParamName].getType() != XmlRpcValue::TypeString || (audioClip->getId() && std::string(result[storeAudioClipAudioClipIdParamName]) != std::string(*audioClip->getId()))) { std::stringstream eMsg; eMsg << "XML-RPC method '" << storeAudioClipCloseMethodName << "' returned unexpected value:\n" << result; throw XmlRpcMethodResponseException(eMsg.str()); } if (!audioClip->getId()) { Ptr::Ref newId(new UniqueId(std::string( result[storeAudioClipAudioClipIdParamName] ))); audioClip->setId(newId); } } /*------------------------------------------------------------------------------ * Acquire resources for an audio clip. *----------------------------------------------------------------------------*/ Ptr::Ref WebStorageClient :: acquireAudioClip(Ptr::Ref sessionId, Ptr::Ref id) const throw (Core::XmlRpcException) { Ptr::Ref audioClip = getAudioClip(sessionId, id); XmlRpcValue parameters; XmlRpcValue result; XmlRpcClient xmlRpcClient(storageServerName.c_str(), storageServerPort, storageServerPath.c_str(), false); parameters.clear(); parameters[acquireAudioClipSessionIdParamName] = sessionId->getId(); parameters[acquireAudioClipAudioClipIdParamName] = std::string(*id); result.clear(); if (!xmlRpcClient.execute(acquireAudioClipMethodName.c_str(), parameters, result)) { xmlRpcClient.close(); std::string eMsg = "cannot execute XML-RPC method '"; eMsg += acquireAudioClipMethodName; eMsg += "'"; throw XmlRpcCommunicationException(eMsg); } xmlRpcClient.close(); if (xmlRpcClient.isFault()) { std::stringstream eMsg; eMsg << "XML-RPC method '" << acquireAudioClipMethodName << "' returned error message:\n" << result; throw Core::XmlRpcMethodFaultException(eMsg.str()); } if (! result.hasMember(acquireAudioClipUrlParamName) || result[acquireAudioClipUrlParamName].getType() != XmlRpcValue::TypeString || ! result.hasMember(acquireAudioClipTokenParamName) || result[acquireAudioClipTokenParamName].getType() != XmlRpcValue::TypeString) { std::stringstream eMsg; eMsg << "XML-RPC method '" << acquireAudioClipMethodName << "' returned unexpected value:\n" << result; throw XmlRpcMethodResponseException(eMsg.str()); } Ptr::Ref uri(new const std::string( result[acquireAudioClipUrlParamName] )); Ptr::Ref token(new const std::string( result[acquireAudioClipTokenParamName] )); audioClip->setUri(uri); audioClip->setToken(token); return audioClip; } /*------------------------------------------------------------------------------ * Release an audio clip. *----------------------------------------------------------------------------*/ void WebStorageClient :: releaseAudioClip(Ptr::Ref sessionId, Ptr::Ref audioClip) const throw (Core::XmlRpcException) { XmlRpcValue parameters; XmlRpcValue result; XmlRpcClient xmlRpcClient(storageServerName.c_str(), storageServerPort, storageServerPath.c_str(), false); parameters.clear(); parameters[releaseAudioClipSessionIdParamName] = sessionId->getId(); parameters[releaseAudioClipTokenParamName] = *audioClip->getToken(); result.clear(); if (!xmlRpcClient.execute(releaseAudioClipMethodName.c_str(), parameters, result)) { xmlRpcClient.close(); std::string eMsg = "cannot execute XML-RPC method '"; eMsg += releaseAudioClipMethodName; eMsg += "'"; throw XmlRpcCommunicationException(eMsg); } xmlRpcClient.close(); if (xmlRpcClient.isFault()) { std::stringstream eMsg; eMsg << "XML-RPC method '" << releaseAudioClipMethodName << "' returned error message:\n" << result; throw Core::XmlRpcMethodFaultException(eMsg.str()); } if (! result.hasMember(releaseAudioClipResultParamName) || result[releaseAudioClipResultParamName].getType() != XmlRpcValue::TypeBoolean) { std::stringstream eMsg; eMsg << "XML-RPC method '" << releaseAudioClipMethodName << "' returned unexpected value:\n" << result; throw XmlRpcMethodResponseException(eMsg.str()); } if (! bool(result[releaseAudioClipResultParamName])) { std::stringstream eMsg; eMsg << "XML-RPC method '" << releaseAudioClipMethodName << "' returned 'false'"; throw XmlRpcMethodResponseException(eMsg.str()); } Ptr::Ref nullpointer; audioClip->setToken(nullpointer); audioClip->setUri(nullpointer); } /*------------------------------------------------------------------------------ * Delete an audio clip. *----------------------------------------------------------------------------*/ void WebStorageClient :: deleteAudioClip(Ptr::Ref sessionId, Ptr::Ref id) throw (Core::XmlRpcException) { XmlRpcValue parameters; XmlRpcValue result; XmlRpcClient xmlRpcClient(storageServerName.c_str(), storageServerPort, storageServerPath.c_str(), false); parameters.clear(); parameters[deleteAudioClipSessionIdParamName] = sessionId->getId(); parameters[deleteAudioClipAudioClipIdParamName] = std::string(*id); result.clear(); if (!xmlRpcClient.execute(deleteAudioClipMethodName.c_str(), parameters, result)) { xmlRpcClient.close(); std::string eMsg = "cannot execute XML-RPC method '"; eMsg += deleteAudioClipMethodName; eMsg += "'"; throw XmlRpcCommunicationException(eMsg); } xmlRpcClient.close(); if (xmlRpcClient.isFault()) { std::stringstream eMsg; eMsg << "XML-RPC method '" << deleteAudioClipMethodName << "' returned error message:\n" << result; throw Core::XmlRpcMethodFaultException(eMsg.str()); } if (! result.hasMember(deleteAudioClipResultParamName) || result[deleteAudioClipResultParamName].getType() != XmlRpcValue::TypeBoolean) { std::stringstream eMsg; eMsg << "XML-RPC method '" << deleteAudioClipMethodName << "' returned unexpected value:\n" << result; throw XmlRpcMethodResponseException(eMsg.str()); } if (! bool(result[deleteAudioClipResultParamName])) { std::stringstream eMsg; eMsg << "XML-RPC method '" << deleteAudioClipMethodName << "' returned 'false'"; throw XmlRpcMethodResponseException(eMsg.str()); } } /*------------------------------------------------------------------------------ * Reset the storage to its initial state. *----------------------------------------------------------------------------*/ void WebStorageClient :: reset(void) throw (Core::XmlRpcException) { XmlRpcValue parameters; XmlRpcValue result; XmlRpcClient xmlRpcClient(storageServerName.c_str(), storageServerPort, storageServerPath.c_str(), false); parameters.clear(); parameters["dummy_param"] = "dummy_value"; result.clear(); if (!xmlRpcClient.execute(resetStorageMethodName.c_str(), parameters, result)) { xmlRpcClient.close(); std::string eMsg = "cannot execute XML-RPC method '"; eMsg += resetStorageMethodName; eMsg += "'"; throw XmlRpcCommunicationException(eMsg); } xmlRpcClient.close(); if (xmlRpcClient.isFault()) { std::stringstream eMsg; eMsg << "XML-RPC method '" << resetStorageMethodName << "' returned error message:\n" << result; throw Core::XmlRpcMethodFaultException(eMsg.str()); } if (! result.hasMember(resetStorageAudioClipResultParamName) || result[resetStorageAudioClipResultParamName].getType() != XmlRpcValue::TypeArray || ! result.hasMember(resetStoragePlaylistResultParamName) || result[resetStoragePlaylistResultParamName].getType() != XmlRpcValue::TypeArray) { std::stringstream eMsg; eMsg << "XML-RPC method '" << resetStorageMethodName << "' returned unexpected value:\n" << result; throw XmlRpcMethodResponseException(eMsg.str()); } XmlRpcValue audioClipArray = result[resetStorageAudioClipResultParamName]; audioClipIds.reset(new std::vector::Ref>); for (int i=0; i < audioClipArray.size(); i++) { if (audioClipArray[i].getType() != XmlRpcValue::TypeString) { std::stringstream eMsg; eMsg << "Non-string audio clip gunid returned by XML-RPC method '" << resetStorageMethodName << "':\n" << result; throw XmlRpcMethodResponseException(eMsg.str()); } Ptr::Ref uniqueId(new UniqueId(std::string( audioClipArray[i]))); audioClipIds->push_back(uniqueId); } XmlRpcValue playlistArray = result[resetStoragePlaylistResultParamName]; playlistIds.reset(new std::vector::Ref>); for (int i=0; i < playlistArray.size(); i++) { if (playlistArray[i].getType() != XmlRpcValue::TypeString) { std::stringstream eMsg; eMsg << "Non-string playlist gunid returned by XML-RPC method '" << resetStorageMethodName << "':\n" << result; throw XmlRpcMethodResponseException(eMsg.str()); } Ptr::Ref uniqueId(new UniqueId(std::string( playlistArray[i]))); playlistIds->push_back(uniqueId); } } /*------------------------------------------------------------------------------ * Search for audio clips or playlists. *----------------------------------------------------------------------------*/ int WebStorageClient :: search(Ptr::Ref sessionId, Ptr::Ref searchCriteria) throw (XmlRpcException) { XmlRpcValue parameters; XmlRpcValue result; XmlRpcClient xmlRpcClient(storageServerName.c_str(), storageServerPort, storageServerPath.c_str(), false); parameters.clear(); parameters[searchSessionIdParamName] = sessionId->getId(); parameters[searchCriteriaParamName] = *searchCriteria; result.clear(); if (!xmlRpcClient.execute(searchMethodName.c_str(), parameters, result)) { xmlRpcClient.close(); std::string eMsg = "cannot execute XML-RPC method '"; eMsg += searchMethodName; eMsg += "'"; throw XmlRpcCommunicationException(eMsg); } xmlRpcClient.close(); if (xmlRpcClient.isFault()) { std::stringstream eMsg; eMsg << "XML-RPC method '" << searchMethodName << "' returned error message:\n" << result; throw Core::XmlRpcMethodFaultException(eMsg.str()); } if (! result.hasMember(searchAudioClipResultParamName) || result[searchAudioClipResultParamName].getType() != XmlRpcValue::TypeArray || ! result.hasMember(searchPlaylistResultParamName) || result[searchPlaylistResultParamName].getType() != XmlRpcValue::TypeArray) { std::stringstream eMsg; eMsg << "XML-RPC method '" << searchMethodName << "' returned unexpected value:\n" << result; throw XmlRpcMethodResponseException(eMsg.str()); } XmlRpcValue audioClipArray = result[searchAudioClipResultParamName]; audioClipIds.reset(new std::vector::Ref>); for (int i=0; i < audioClipArray.size(); i++) { if (audioClipArray[i].getType() != XmlRpcValue::TypeString) { std::stringstream eMsg; eMsg << "Non-string audio clip gunid returned by XML-RPC method '" << searchMethodName << "':\n" << result; throw XmlRpcMethodResponseException(eMsg.str()); } Ptr::Ref uniqueId(new UniqueId(std::string( audioClipArray[i]))); audioClipIds->push_back(uniqueId); } XmlRpcValue playlistArray = result[searchPlaylistResultParamName]; playlistIds.reset(new std::vector::Ref>); for (int i=0; i < playlistArray.size(); i++) { if (playlistArray[i].getType() != XmlRpcValue::TypeString) { std::stringstream eMsg; eMsg << "Non-string playlist gunid returned by XML-RPC method '" << searchMethodName << "':\n" << result; throw XmlRpcMethodResponseException(eMsg.str()); } Ptr::Ref uniqueId(new UniqueId(std::string( playlistArray[i]))); playlistIds->push_back(uniqueId); } if (! result.hasMember(searchAudioClipCountParamName) || result[searchAudioClipCountParamName].getType() != XmlRpcValue::TypeInt || ! result.hasMember(searchPlaylistCountParamName) || result[searchPlaylistCountParamName].getType() != XmlRpcValue::TypeInt) { std::stringstream eMsg; eMsg << "Missing or bad count returned by XML-RPC method '" << searchMethodName << "':\n" << result; throw XmlRpcMethodResponseException(eMsg.str()); } return int(result[searchAudioClipCountParamName]) + int(result[searchPlaylistCountParamName]); } /*------------------------------------------------------------------------------ * Return a list of all playlists in the storage. *----------------------------------------------------------------------------*/ Ptr::Ref> >::Ref WebStorageClient :: getAllPlaylists(Ptr::Ref sessionId, const int limit, const int offset) throw (XmlRpcException) { Ptr::Ref criteria(new SearchCriteria("playlist")); criteria->setLimit(limit); criteria->setOffset(offset); search(sessionId, criteria); Ptr::Ref> >::Ref playlists( new std::vector::Ref>); std::vector::Ref>::const_iterator it, end; it = getPlaylistIds()->begin(); end = getPlaylistIds()->end(); while (it != end) { playlists->push_back(getPlaylist(sessionId, *it)); ++it; } return playlists; } /*------------------------------------------------------------------------------ * Return a list of all audio clips in the storage. *----------------------------------------------------------------------------*/ Ptr::Ref> >::Ref WebStorageClient :: getAllAudioClips(Ptr::Ref sessionId, const int limit, const int offset) throw (XmlRpcException) { Ptr::Ref criteria(new SearchCriteria("audioClip")); criteria->setLimit(limit); criteria->setOffset(offset); search(sessionId, criteria); Ptr::Ref> >::Ref audioClips( new std::vector::Ref>); std::vector::Ref>::const_iterator it, end; it = getAudioClipIds()->begin(); end = getAudioClipIds()->end(); while (it != end) { audioClips->push_back(getAudioClip(sessionId, *it)); ++it; } return audioClips; }