diff --git a/livesupport/modules/core/include/LiveSupport/Core/Playlist.h b/livesupport/modules/core/include/LiveSupport/Core/Playlist.h index 0a2c58ce9..ad3618200 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.23 $ + Version : $Revision: 1.24 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/include/LiveSupport/Core/Playlist.h,v $ ------------------------------------------------------------------------------*/ @@ -93,7 +93,7 @@ using namespace boost::posix_time; * * * @author $Author: fgerlits $ - * @version $Revision: 1.23 $ + * @version $Revision: 1.24 $ */ class Playlist : public Configurable, public Playable @@ -492,20 +492,6 @@ class Playlist : public Configurable, Ptr::Ref fadeInfo) throw (std::invalid_argument); - /** - * 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 - * @exception std::invalid_argument if the playlist does not contain - * an audio clip with the specified relative offset - */ - void - removeAudioClip(Ptr::Ref relativeOffset) - throw (std::invalid_argument); - /** * Remove a playlist element from the playlist. * diff --git a/livesupport/modules/core/src/Playlist.cxx b/livesupport/modules/core/src/Playlist.cxx index b25d205df..ef6c4d418 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.19 $ + Version : $Revision: 1.20 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/src/Playlist.cxx,v $ ------------------------------------------------------------------------------*/ @@ -201,24 +201,6 @@ 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) - throw (std::invalid_argument) -{ - // this returns the number of elements found and erased - if (!elementList->erase(*relativeOffset)) { - std::string eMsg = "no audio clip at the specified relative offset"; - throw std::invalid_argument(eMsg); - } -} - - /*------------------------------------------------------------------------------ * Remove a playlist element from the playlist. *----------------------------------------------------------------------------*/ diff --git a/livesupport/modules/storage/src/WebStorageClient.cxx b/livesupport/modules/storage/src/WebStorageClient.cxx index 0dd283d9c..a9d262759 100644 --- a/livesupport/modules/storage/src/WebStorageClient.cxx +++ b/livesupport/modules/storage/src/WebStorageClient.cxx @@ -22,7 +22,7 @@ Author : $Author: fgerlits $ - Version : $Revision: 1.16 $ + Version : $Revision: 1.17 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/storage/src/WebStorageClient.cxx,v $ ------------------------------------------------------------------------------*/ @@ -177,6 +177,8 @@ static const std::string resetStorageMethodName static const std::string resetStorageResultParamName = "gunids"; +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ playlist methods */ + /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ storage server constants: existsPlaylist */ /*------------------------------------------------------------------------------ @@ -265,12 +267,104 @@ static const std::string editPlaylistUrlParamName = "url"; 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 = "status"; + + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ storage server constants: acquirePlaylist */ +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ storage server constants: releasePlaylist */ + + + + + + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 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"; + + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 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"; + + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ audio clip methods */ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ storage server constants: existsAudioClip */ @@ -333,8 +427,6 @@ static const std::string getAudioClipTokenParamName = "token"; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ storage server constants: storeAudioClip */ -// TODO: fix; this method does not exist any more - /*------------------------------------------------------------------------------ * The name of the opening 'store audio clip' method on the storage server *----------------------------------------------------------------------------*/ @@ -704,6 +796,39 @@ Ptr::Ref WebStorageClient :: editPlaylist(Ptr::Ref sessionId, Ptr::Ref id) const throw (StorageException) +{ + Ptr::Ref playlist(new Playlist(id)); + Ptr::Ref url, token; + editPlaylistGetUrl(sessionId, id, url, token); + + 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); + + return playlist; +} + + +void +WebStorageClient :: editPlaylistGetUrl(Ptr::Ref sessionId, + Ptr::Ref id, + Ptr::Ref& url, + Ptr::Ref& token) const + throw (StorageException) { XmlRpcValue parameters; XmlRpcValue result; @@ -749,31 +874,8 @@ WebStorageClient :: editPlaylist(Ptr::Ref sessionId, throw XmlRpcMethodResponseException(eMsg.str()); } - const std::string url = result[getPlaylistUrlParamName]; - - 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"); - } - - Ptr::Ref token(new const std::string( - result[getPlaylistTokenParamName] )); - playlist->setToken(token); - - return playlist; + url.reset(new const std::string(result[getPlaylistUrlParamName])); + token.reset(new const std::string(result[getPlaylistTokenParamName])); } @@ -785,6 +887,63 @@ WebStorageClient :: savePlaylist(Ptr::Ref sessionId, Ptr::Ref playlist) const throw (StorageException) { + if (!playlist || !playlist->getToken()) { + throw InvalidArgumentException("playlist has no token field"); + } + + 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)) { + std::string eMsg = "cannot execute XML-RPC method '"; + eMsg += savePlaylistMethodName; + eMsg += "'"; + throw XmlRpcCommunicationException(eMsg); + } + + if (xmlRpcClient.isFault()) { + std::stringstream eMsg; + eMsg << "XML-RPC method '" + << savePlaylistMethodName + << "' returned error message:\n" + << result; + throw XmlRpcMethodFaultException(eMsg.str()); + } + + if (! result.hasMember(savePlaylistResultParamName) + || result[savePlaylistResultParamName].getType() + != XmlRpcValue::TypeBoolean) { + std::stringstream eMsg; + eMsg << "XML-RPC method '" + << savePlaylistMethodName + << "' returned unexpected value:\n" + << result; + throw XmlRpcMethodResponseException(eMsg.str()); + } + + if (! bool(result[savePlaylistResultParamName])) { + std::stringstream eMsg; + eMsg << "XML-RPC method '" + << savePlaylistMethodName + << "' returned 'false'"; + throw XmlRpcMethodResponseException(eMsg.str()); + } + + Ptr::Ref nullpointer; + playlist->setToken(nullpointer); } @@ -821,7 +980,54 @@ WebStorageClient :: deletePlaylist(Ptr::Ref sessionId, Ptr::Ref id) throw (StorageException) { + 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)) { + std::string eMsg = "cannot execute XML-RPC method '"; + eMsg += deletePlaylistMethodName; + eMsg += "'"; + throw XmlRpcCommunicationException(eMsg); + } + + if (xmlRpcClient.isFault()) { + std::stringstream eMsg; + eMsg << "XML-RPC method '" + << deletePlaylistMethodName + << "' returned error message:\n" + << result; + throw 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()); + } } @@ -845,7 +1051,62 @@ Ptr::Ref WebStorageClient :: createPlaylist(Ptr::Ref sessionId) throw (StorageException) { - Ptr::Ref playlist(new Playlist); + XmlRpcValue parameters; + XmlRpcValue result; + + XmlRpcClient xmlRpcClient(storageServerName.c_str(), storageServerPort, + storageServerPath.c_str(), false); + + parameters.clear(); + parameters[createPlaylistSessionIdParamName] + = sessionId->getId(); + parameters[createPlaylistPlaylistIdParamName] + = std::string(*UniqueId::generateId()); // TODO: the server + // should generate the ID + result.clear(); + if (!xmlRpcClient.execute(createPlaylistMethodName.c_str(), + parameters, result)) { + std::string eMsg = "cannot execute XML-RPC method '"; + eMsg += createPlaylistMethodName; + eMsg += "'"; + throw XmlRpcCommunicationException(eMsg); + } + + if (xmlRpcClient.isFault()) { + std::stringstream eMsg; + eMsg << "XML-RPC method '" + << createPlaylistMethodName + << "' returned error message:\n" + << result; + throw 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); + + savePlaylist(sessionId, playlist); + + token.reset(); + playlist->setToken(token); + return playlist; } diff --git a/livesupport/modules/storage/src/WebStorageClient.h b/livesupport/modules/storage/src/WebStorageClient.h index 9b3bcae2b..a94ee0e0c 100644 --- a/livesupport/modules/storage/src/WebStorageClient.h +++ b/livesupport/modules/storage/src/WebStorageClient.h @@ -22,7 +22,7 @@ Author : $Author: fgerlits $ - Version : $Revision: 1.11 $ + Version : $Revision: 1.12 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/storage/src/WebStorageClient.h,v $ ------------------------------------------------------------------------------*/ @@ -99,7 +99,7 @@ using namespace LiveSupport::Core; * * * @author $Author: fgerlits $ - * @version $Revision: 1.11 $ + * @version $Revision: 1.12 $ */ class WebStorageClient : virtual public Configurable, @@ -131,6 +131,24 @@ class WebStorageClient : */ std::string storageServerPath; + /** + * Auxilliary method used by editPlaylist() and createPlaylist(). + * Opens the playlist for editing, and returns its URL. + * + * @param sessionId the session ID from the authentication client + * @param id the id of the playlist to return. + * @param url pointer in which the URL of the playlist is returned. + * @param token pointer in which the token of the playlist is returned. + * @exception StorageException if there is a problem with the XML-RPC + * call or no playlist with the specified + * id exists. + */ + void + editPlaylistGetUrl(Ptr::Ref sessionId, + Ptr::Ref id, + Ptr::Ref& url, + Ptr::Ref& token) const + throw (StorageException); public: /** @@ -282,6 +300,10 @@ class WebStorageClient : /** * Return a list of all playlists in the playlist store. * + * Since this makes no sense whatsoever, this method currently returns + * an empty list. It will be replaced by a method which uses + * locstor.searchMetadata. + * * @param sessionId the session ID from the authentication client * @return a vector containing the playlists. * @exception StorageException if there is a problem with the XML-RPC diff --git a/livesupport/modules/storage/src/WebStorageClientTest.cxx b/livesupport/modules/storage/src/WebStorageClientTest.cxx index 5861dccd9..27e4aa0bf 100644 --- a/livesupport/modules/storage/src/WebStorageClientTest.cxx +++ b/livesupport/modules/storage/src/WebStorageClientTest.cxx @@ -22,7 +22,7 @@ Author : $Author: fgerlits $ - Version : $Revision: 1.18 $ + Version : $Revision: 1.19 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/storage/src/WebStorageClientTest.cxx,v $ ------------------------------------------------------------------------------*/ @@ -186,7 +186,7 @@ WebStorageClientTest :: playlistTest(void) CPPUNIT_FAIL(e.what()); } CPPUNIT_ASSERT(uniqueIdVector->size() > 0); -// Ptr::Ref audioClipId01 = uniqueIdVector->at(0); + Ptr::Ref audioClipId = uniqueIdVector->at(0); Ptr::Ref sessionId; try { @@ -198,9 +198,29 @@ WebStorageClientTest :: playlistTest(void) CPPUNIT_ASSERT(sessionId); - // test ... + // test createPlaylist() + Ptr::Ref playlist; + try{ + playlist = wsc->createPlaylist(sessionId); + } + catch (StorageException &e) { + CPPUNIT_FAIL(e.what()); + } + CPPUNIT_ASSERT(playlist); + Ptr::Ref playlistIdxx = playlist->getId(); + + + // test existsPlaylist() + bool exists = false; + try { + exists = wsc->existsPlaylist(sessionId, playlistIdxx); + } + catch (StorageException &e) { + CPPUNIT_FAIL(e.what()); + } + CPPUNIT_ASSERT(exists); + Ptr::Ref playlistId77(new UniqueId(77)); - bool exists = true; try { exists = wsc->existsPlaylist(sessionId, playlistId77); } @@ -210,10 +230,84 @@ WebStorageClientTest :: playlistTest(void) CPPUNIT_ASSERT(!exists); + // test editPlaylist() + try { + playlist = wsc->editPlaylist(sessionId, playlistIdxx); + } + catch (StorageException &e) { + CPPUNIT_FAIL(e.what()); + } + CPPUNIT_ASSERT(playlist); + + try { + playlist = wsc->editPlaylist(sessionId, playlistIdxx); + CPPUNIT_FAIL("allowed to open playlist for editing twice"); + } + catch (XmlRpcMethodFaultException &e) { + } + catch (StorageException &e) { + std::string eMsg = "editPlaylist() threw unexpected exception:\n"; + CPPUNIT_FAIL(eMsg + e.what()); + } + CPPUNIT_ASSERT(playlist); + + Ptr::Ref audioClip; + try { + audioClip = wsc->getAudioClip(sessionId, audioClipId); + } + catch (StorageException &e) { + CPPUNIT_FAIL(e.what()); + } + Ptr::Ref relativeOffset(new time_duration(0,0,0,0)); + playlist->addAudioClip(audioClip, relativeOffset); + CPPUNIT_ASSERT(playlist->valid()); // WARNING: side effect; fixes the + // playlength of the playlist + try { + Ptr::Ref throwAwayPlaylist + = wsc->getPlaylist(sessionId, playlistIdxx); + // this should be OK, get old copy + CPPUNIT_ASSERT(throwAwayPlaylist->getPlaylength() + ->total_seconds() == 0); + } + catch (StorageException &e) { + CPPUNIT_FAIL(e.what()); + } + try { + wsc->savePlaylist(sessionId, playlist); + } + catch (StorageException &e) { + CPPUNIT_FAIL(e.what()); + } + // test getPlaylist() + Ptr::Ref newPlaylist; + try { + newPlaylist = wsc->getPlaylist(sessionId, playlistIdxx); + } + catch (StorageException &e) { + CPPUNIT_FAIL(e.what()); + } + CPPUNIT_ASSERT(newPlaylist); + CPPUNIT_ASSERT(newPlaylist->getPlaylength()->total_seconds() + == playlist->getPlaylength()->total_seconds()); + // NOTE: we really ought to define == for playlists... + // test deletePlaylist() + try { + wsc->deletePlaylist(sessionId, playlistIdxx); + } + catch (StorageException &e) { + CPPUNIT_FAIL(e.what()); + } + try { + exists = wsc->existsPlaylist(sessionId, playlistIdxx); + } + catch (StorageException &e) { + CPPUNIT_FAIL(e.what()); + } + CPPUNIT_ASSERT(!exists); } diff --git a/livesupport/products/scheduler/src/RemoveAudioClipFromPlaylistMethod.cxx b/livesupport/products/scheduler/src/RemoveAudioClipFromPlaylistMethod.cxx index 0b6607b14..e0f629a91 100644 --- a/livesupport/products/scheduler/src/RemoveAudioClipFromPlaylistMethod.cxx +++ b/livesupport/products/scheduler/src/RemoveAudioClipFromPlaylistMethod.cxx @@ -22,7 +22,7 @@ Author : $Author: fgerlits $ - Version : $Revision: 1.7 $ + Version : $Revision: 1.8 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/products/scheduler/src/RemoveAudioClipFromPlaylistMethod.cxx,v $ ------------------------------------------------------------------------------*/ @@ -165,7 +165,7 @@ RemoveAudioClipFromPlaylistMethod :: execute( } try { // and finally, the beef - playlist->removeAudioClip(relativeOffset); + playlist->removePlaylistElement(relativeOffset); } catch(std::invalid_argument &e) { XmlRpcTools::markError(errorId+6,