cleaned up some major dogsh*t left by a certain person who shall not be named

incidentally, fixed bug #1465
This commit is contained in:
fgerlits 2005-09-21 15:27:01 +00:00
parent df31c8d72f
commit 37101d2166
9 changed files with 416 additions and 191 deletions

View file

@ -156,6 +156,9 @@ class Playable : public boost::enable_shared_from_this<Playable>
* Return the token which is used to identify this audio clip
* or playlist to the storage server.
*
* The token is set when the Playable object is acquired and
* unset (made null again) when it is released.
*
* @return the token.
*/
virtual Ptr<const std::string>::Ref
@ -165,6 +168,9 @@ class Playable : public boost::enable_shared_from_this<Playable>
* Set the token which is used to identify this audio clip
* or playlist to the storage server.
*
* The token is set when the Playable object is acquired and
* unset (made null again) when it is released.
*
* @param token a new token.
*/
virtual void

View file

@ -127,6 +127,28 @@ using namespace boost::posix_time;
* &lt;!ATTLIST playlist playlength NMTOKEN #IMPLIED &gt;
* </code></pre>
*
* A Playlist can be of various kinds, depending on what we want to use it
* for, and how we got it from the StorageClientInterface:
* <ul>
* <li>A playlist obtained by getPlaylist() has its <code>uri</code>,
* <code>token</code> and <code>editToken</code> fields all unset
* (i.e., null). Such playlist contain sub-playlists which
* are just stubs, i.e., <code>id, title, playlength</code> triples,
* without actual references to its content objects.</li>
* <li>A playlist obtained by acquirePlaylist() has its <code>uri</code>
* and <code>token</code> fields set, but its <code>editToken</code>
* field unset. These are complete Playlist objects, and their
* sub-playlists contain references to all their sub-objects etc.
* The sub-playlists have their <code>uri</code> fields set, which
* allows them to be played by the audio player, but their
* <code>token</code> field is unset, because these sub-playlists
* are acquired and will be released recursively when the outermost
* playlist containing them is acquired and released.</li>
* <li>A playlist obtained by editPlaylist() has its <code>editToken</code>
* field set (but <code>uri</code> and <code>token</code> unset).
* The sub-playlists of these are also just stubs.</li>
* </ul>
*
* @author $Author$
* @version $Revision$
*/
@ -160,10 +182,17 @@ class Playlist : public Configurable,
Ptr<const std::string>::Ref uri;
/**
* The token given to this playlist by the storage server.
* The token given to this playlist by the storage server when
* the playlist is acquired; removed when it is released.
*/
Ptr<const std::string>::Ref token;
/**
* The token given to this playlist by the storage server when
* it is opened for editing; removed when it is saved or reverted.
*/
Ptr<const std::string>::Ref editToken;
/**
* A map type for storing the playlist elements associated with
* this playlist, indexed by their relative offsets.
@ -464,6 +493,9 @@ class Playlist : public Configurable,
* Return the token which is used to identify this
* playlist to the storage server.
*
* The token is set when the Playable object is acquired and
* unset (made null again) when it is released.
*
* @return the token.
*/
virtual Ptr<const std::string>::Ref
@ -476,6 +508,9 @@ class Playlist : public Configurable,
* Set the token which is used to identify this
* playlist to the storage server.
*
* The token is set when the Playable object is acquired and
* unset (made null again) when it is released.
*
* @param token a new token.
*/
virtual void
@ -485,6 +520,37 @@ class Playlist : public Configurable,
this->token = token;
}
/**
* Return the token which is used to identify this
* playlist to the storage server.
*
* The edit token is set when the Playable object is opened for
* editing and unset (made null again) when it is saved or reverted.
*
* @return the token.
*/
virtual Ptr<const std::string>::Ref
getEditToken(void) const throw ()
{
return editToken;
}
/**
* Set the token which is used to identify this
* playlist to the storage server.
*
* The edit token is set when the Playable object is opened for
* editing and unset (made null again) when it is saved or reverted.
*
* @param token a new token.
*/
virtual void
setEditToken(Ptr<const std::string>::Ref token)
throw ()
{
this->editToken = token;
}
/**
* Test whether the playlist is locked for editing.
*
@ -493,7 +559,7 @@ class Playlist : public Configurable,
bool
isLocked() const throw ()
{
return (token.get() != 0);
return (editToken.get() != 0);
}
@ -560,10 +626,10 @@ class Playlist : public Configurable,
* Checks the type of the playlist, and calls either addAudioClip()
* or addPlaylist().
*
* @param audioClip the new playable item to be added
* @param relativeOffset the start of the playable item, relative
* to the start of the playlist
* @param fadeInfo the fade in / fade out info (optional)
* @param playable the new playable item to be added
* @param relativeOffset the start of the playable item, relative
* to the start of the playlist
* @param fadeInfo the fade in / fade out info (optional)
* @return the ID of the new PlaylistElement
* @exception std::invalid_argument if playable is neither an AudioClip
* nor a Playlist
@ -711,7 +777,7 @@ class Playlist : public Configurable,
/**
* Return a partial XML representation of this audio clip or playlist.
*
* This is a string containing a single <playlist>
* This is a string containing a single &lt;playlist&gt;
* XML element, with minimal information (ID, title, playlength)
* only, without an XML header or any other metadata.
*
@ -728,8 +794,8 @@ class Playlist : public Configurable,
* Return a complete XML representation of this playlist.
*
* This is a string containing a an XML document with a
* <playlist> root node, together with an XML header and a
* <metadata> element (for the outermost playlist only).
* &lt;playlist&gt; root node, together with an XML header and a
* &lt;metadata&gt; element (for the outermost playlist only).
*
* The encoding is UTF-8. IDs are 16-digit hexadecimal numbers,
* time durations have the format "hh:mm:ss.ssssss".
@ -751,8 +817,8 @@ class Playlist : public Configurable,
* All other metadata fields in the audio clips and sub-playlists
* will be lost.
*
* The <i>uri</i> and <i>token</i> fields are currently not part
* of the XML document string returned.
* The <i>uri</i>, <i>token</i> and <i>editToken</i> fields are not
* part of the XML document string returned.
*
* @return a string representation of the playlist as an XML document
*/

View file

@ -203,6 +203,7 @@ class PlaylistElement : public Configurable
this->audioClip = audioClip;
this->playable = audioClip;
this->fadeInfo = fadeInfo;
this->type = AudioClipType;
}
/**
@ -351,6 +352,31 @@ class PlaylistElement : public Configurable
return playable;
}
/**
* Set the Playable instance (an AudioClip or a Playlist)
* associated with the playlist element.
*
* This is used by WebStorageClient::acquirePlaylist() to replace
* a stub (id, title, playlength only) sub-playlist with a full one.
*
* @param playable the new Playable object.
*/
void
setPlayable(Ptr<Playable>::Ref playable) throw ()
{
this->playable = playable;
switch (playable->getType()) {
case Playable::AudioClipType :
audioClip = playable->getAudioClip();
type = AudioClipType;
break;
case Playable::PlaylistType :
playlist = playable->getPlaylist();
type = PlaylistType;
break;
}
}
/**
* Return the audio clip associated with the playlist element.
*

View file

@ -346,7 +346,7 @@ TestStorageClient :: getPlaylist(Ptr<SessionId>::Ref sessionId,
EditedPlaylistsType::const_iterator
editIt = editedPlaylists.find(id->getId());
if (editIt != editedPlaylists.end() // is being edited
&& (*editIt->second->getToken() == sessionId->getId())) { // by us
&& (*editIt->second->getEditToken() == sessionId->getId())) { // by us
playlist = editIt->second;
} else {
PlaylistMapType::const_iterator
@ -378,8 +378,8 @@ TestStorageClient :: editPlaylist(Ptr<SessionId>::Ref sessionId,
}
Ptr<Playlist>::Ref playlist = getPlaylist(sessionId, id);
Ptr<std::string>::Ref token(new std::string(sessionId->getId()));
playlist->setToken(token);
Ptr<std::string>::Ref editToken(new std::string(sessionId->getId()));
playlist->setEditToken(editToken);
editedPlaylists[id->getId()] = playlist;
return playlist;
@ -398,11 +398,11 @@ TestStorageClient :: savePlaylist(Ptr<SessionId>::Ref sessionId,
throw XmlRpcException("missing session ID argument");
}
if (! playlist->getToken()) {
if (! playlist->getEditToken()) {
throw XmlRpcException("savePlaylist() called without editPlaylist()");
}
if (sessionId->getId() != *playlist->getToken()) {
if (sessionId->getId() != *playlist->getEditToken()) {
throw XmlRpcException("tried to save playlist in different session"
" than the one it was opened in???");
}
@ -411,12 +411,12 @@ TestStorageClient :: savePlaylist(Ptr<SessionId>::Ref sessionId,
editIt = editedPlaylists.find(playlist->getId()->getId());
if ((editIt == editedPlaylists.end())
|| (*playlist->getToken() != *editIt->second->getToken())) {
|| (*playlist->getEditToken() != *editIt->second->getEditToken())) {
throw XmlRpcException("savePlaylist() called without editPlaylist()");
}
Ptr<std::string>::Ref nullPointer;
playlist->setToken(nullPointer);
playlist->setEditToken(nullPointer);
PlaylistMapType::iterator
storeIt = playlistMap.find(playlist->getId()->getId());
@ -434,7 +434,7 @@ TestStorageClient :: savePlaylist(Ptr<SessionId>::Ref sessionId,
* Revert a playlist to its pre-editing state.
*----------------------------------------------------------------------------*/
void
TestStorageClient :: revertPlaylist(Ptr<const std::string>::Ref playlistToken)
TestStorageClient :: revertPlaylist(Ptr<const std::string>::Ref editToken)
throw (XmlRpcException)
{
std::cerr << "TestStorageClient :: revertPlaylist"

View file

@ -321,13 +321,13 @@ class TestStorageClient :
* the playlist (and lose all changes) at the next login using
* this method.
*
* @param playlistToken the token of the edited playlist
* @param editToken the token of the edited playlist
* @exception XmlRpcException if there is a problem with the XML-RPC
* call or no playlist with the specified
* token exists.
*/
virtual void
revertPlaylist(Ptr<const std::string>::Ref playlistToken)
revertPlaylist(Ptr<const std::string>::Ref editToken)
throw (XmlRpcException);

View file

@ -847,13 +847,13 @@ WebStorageClient :: createPlaylist(Ptr<SessionId>::Ref sessionId)
Ptr<time_duration>::Ref playlength(new time_duration(0,0,0,0));
Ptr<Playlist>::Ref playlist(new Playlist(newId, playlength));
playlist->setToken(token);
playlist->setEditToken(token);
editedPlaylists[newId->getId()] = std::make_pair(sessionId, playlist);
savePlaylist(sessionId, playlist);
token.reset();
playlist->setToken(token);
playlist->setEditToken(token);
return playlist->getId();
}
@ -918,9 +918,8 @@ WebStorageClient :: existsPlaylist(Ptr<SessionId>::Ref sessionId,
* Return a playlist to be displayed.
*----------------------------------------------------------------------------*/
Ptr<Playlist>::Ref
WebStorageClient :: getPlaylist(Ptr<SessionId>::Ref sessionId,
Ptr<UniqueId>::Ref id,
bool deep) const
WebStorageClient :: getPlaylist(Ptr<SessionId>::Ref sessionId,
Ptr<UniqueId>::Ref id) const
throw (Core::XmlRpcException)
{
EditedPlaylistsType::const_iterator
@ -940,7 +939,7 @@ WebStorageClient :: getPlaylist(Ptr<SessionId>::Ref sessionId,
parameters.clear();
parameters[getPlaylistSessionIdParamName] = sessionId->getId();
parameters[getPlaylistPlaylistIdParamName] = std::string(*id);
parameters[getPlaylistRecursiveParamName] = deep;
parameters[getPlaylistRecursiveParamName] = false;
result.clear();
if (!xmlRpcClient.execute(getPlaylistOpenMethodName.c_str(),
@ -960,25 +959,33 @@ WebStorageClient :: getPlaylist(Ptr<SessionId>::Ref sessionId,
<< result;
throw Core::XmlRpcMethodFaultException(eMsg.str());
}
if (! result.hasMember(getPlaylistUrlParamName)
|| result[getPlaylistUrlParamName].getType()
!= XmlRpcValue::TypeString
|| ! result.hasMember(getPlaylistTokenParamName)
if (! result.hasMember(getPlaylistTokenParamName)
|| result[getPlaylistTokenParamName].getType()
!= XmlRpcValue::TypeString) {
std::stringstream eMsg;
eMsg << "XML-RPC method '"
<< getPlaylistOpenMethodName
<< "' returned unexpected value:\n"
<< result;
<< getPlaylistOpenMethodName
<< "' returned unexpected value:\n"
<< result;
throw XmlRpcMethodResponseException(eMsg.str());
}
Ptr<const std::string>::Ref token(new std::string(
result[getPlaylistTokenParamName] ));
if (! result.hasMember(getPlaylistUrlParamName)
|| result[getPlaylistUrlParamName].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<Playlist>::Ref playlist(new Playlist(id));
Ptr<Playlist>::Ref playlist(new Playlist(id));
try {
Ptr<xmlpp::DomParser>::Ref parser(new xmlpp::DomParser());
parser->parse_file(url);
@ -994,48 +1001,10 @@ WebStorageClient :: getPlaylist(Ptr<SessionId>::Ref sessionId,
throw XmlRpcInvalidDataException(
"error parsing playlist metafile");
}
playlist->setToken(token);
if (deep) {
playlist = acquirePlaylist(playlist, result);
}
parameters.clear();
parameters[getPlaylistSessionIdParamName] = sessionId->getId();
parameters[getPlaylistTokenParamName] = token;
releasePlaylistFromServer(playlist);
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;
}
@ -1053,9 +1022,9 @@ WebStorageClient :: editPlaylist(Ptr<SessionId>::Ref sessionId,
" being edited");
}
Ptr<const std::string>::Ref url, token;
Ptr<const std::string>::Ref url, editToken;
editPlaylistGetUrl(sessionId, id, url, token);
editPlaylistGetUrl(sessionId, id, url, editToken);
Ptr<Playlist>::Ref playlist(new Playlist(id));
try {
@ -1074,7 +1043,7 @@ WebStorageClient :: editPlaylist(Ptr<SessionId>::Ref sessionId,
"error parsing playlist metafile");
}
playlist->setToken(token);
playlist->setEditToken(editToken);
editedPlaylists[id->getId()] = std::make_pair(sessionId, playlist);
return playlist;
@ -1088,7 +1057,7 @@ void
WebStorageClient :: editPlaylistGetUrl(Ptr<SessionId>::Ref sessionId,
Ptr<UniqueId>::Ref id,
Ptr<const std::string>::Ref& url,
Ptr<const std::string>::Ref& token)
Ptr<const std::string>::Ref& editToken)
throw (Core::XmlRpcException)
{
XmlRpcValue parameters;
@ -1138,7 +1107,7 @@ WebStorageClient :: editPlaylistGetUrl(Ptr<SessionId>::Ref sessionId,
}
url.reset(new const std::string(result[getPlaylistUrlParamName]));
token.reset(new const std::string(result[getPlaylistTokenParamName]));
editToken.reset(new const std::string(result[getPlaylistTokenParamName]));
}
@ -1150,8 +1119,8 @@ WebStorageClient :: savePlaylist(Ptr<SessionId>::Ref sessionId,
Ptr<Playlist>::Ref playlist)
throw (Core::XmlRpcException)
{
if (!playlist || !playlist->getToken()) {
throw XmlRpcInvalidArgumentException("playlist has no token field");
if (!playlist || !playlist->getEditToken()) {
throw XmlRpcInvalidArgumentException("playlist has no editToken field");
}
EditedPlaylistsType::iterator
@ -1174,7 +1143,7 @@ WebStorageClient :: savePlaylist(Ptr<SessionId>::Ref sessionId,
parameters[savePlaylistSessionIdParamName]
= sessionId->getId();
parameters[savePlaylistTokenParamName]
= *playlist->getToken();
= *playlist->getEditToken();
parameters[savePlaylistNewPlaylistParamName]
= std::string(*playlist->getXmlDocumentString());
@ -1212,7 +1181,7 @@ WebStorageClient :: savePlaylist(Ptr<SessionId>::Ref sessionId,
}
Ptr<const std::string>::Ref nullpointer;
playlist->setToken(nullpointer);
playlist->setEditToken(nullpointer);
}
@ -1220,10 +1189,10 @@ WebStorageClient :: savePlaylist(Ptr<SessionId>::Ref sessionId,
* Revert a playlist to its pre-editing state.
*----------------------------------------------------------------------------*/
void
WebStorageClient :: revertPlaylist(Ptr<const std::string>::Ref playlistToken)
WebStorageClient :: revertPlaylist(Ptr<const std::string>::Ref editToken)
throw (XmlRpcException)
{
if (!playlistToken) {
if (!editToken) {
throw XmlRpcInvalidArgumentException("null pointer in argument");
}
@ -1237,7 +1206,7 @@ WebStorageClient :: revertPlaylist(Ptr<const std::string>::Ref playlistToken)
parameters[revertPlaylistSessionIdParamName] // dummy parameter
= "";
parameters[revertPlaylistTokenParamName]
= *playlistToken;
= *editToken;
result.clear();
if (!xmlRpcClient.execute(revertPlaylistMethodName.c_str(),
@ -1273,22 +1242,115 @@ WebStorageClient :: revertPlaylist(Ptr<const std::string>::Ref playlistToken)
/*------------------------------------------------------------------------------
* Acquire resources for a playlist.
* Acquire resources for a playlist, step 1: execute the XML-RPC call.
*----------------------------------------------------------------------------*/
Ptr<Playlist>::Ref
WebStorageClient :: acquirePlaylist(Ptr<Playlist>::Ref oldPlaylist,
XmlRpcValue & result) const
WebStorageClient :: acquirePlaylist(Ptr<SessionId>::Ref sessionId,
Ptr<UniqueId>::Ref id) const
throw (Core::XmlRpcException)
{
XmlRpcValue content;
int index;
Ptr<time_duration>::Ref playlength = oldPlaylist->getPlaylength();
Ptr<Playlist>::Ref newPlaylist(new Playlist(oldPlaylist->getId(),
playlength));
newPlaylist->setTitle(oldPlaylist->getTitle());
newPlaylist->setToken(oldPlaylist->getToken());
// TODO: copy over all metadata as well
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);
parameters[getPlaylistRecursiveParamName] = true;
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(getPlaylistTokenParamName)
|| result[getPlaylistTokenParamName].getType()
!= XmlRpcValue::TypeString) {
std::stringstream eMsg;
eMsg << "XML-RPC method '"
<< getPlaylistOpenMethodName
<< "' returned unexpected value:\n"
<< result;
throw XmlRpcMethodResponseException(eMsg.str());
}
Ptr<const std::string>::Ref token(new std::string(
result[getPlaylistTokenParamName] ));
Ptr<Playlist>::Ref playlist = acquirePlaylist(id, result);
playlist->setToken(token);
return playlist;
}
/*------------------------------------------------------------------------------
* Acquire resources for a playlist, step 2: create the temp files.
*----------------------------------------------------------------------------*/
Ptr<Playlist>::Ref
WebStorageClient :: acquirePlaylist(Ptr<UniqueId>::Ref id,
XmlRpcValue & content) const
throw (Core::XmlRpcException)
{
// construct the playlist
if (! content.hasMember(getPlaylistUrlParamName)
|| content[getPlaylistUrlParamName].getType()
!= XmlRpcValue::TypeString) {
std::stringstream eMsg;
eMsg << "XML-RPC method '"
<< getPlaylistOpenMethodName
<< "' returned unexpected value:\n"
<< content;
throw XmlRpcMethodResponseException(eMsg.str());
}
const std::string url = content[getPlaylistUrlParamName];
Ptr<Playlist>::Ref playlist(new Playlist(id));
try {
Ptr<xmlpp::DomParser>::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 XmlRpcInvalidDataException(
"semantic error in playlist metafile");
} catch (xmlpp::exception &e) {
throw XmlRpcInvalidDataException(
"error parsing playlist metafile");
}
// read the content array corresponding to the playlist
if (! content.hasMember(getPlaylistContentParamName)
|| content[getPlaylistContentParamName].getType()
!= XmlRpcValue::TypeArray) {
std::stringstream eMsg;
eMsg << "XML-RPC method '"
<< getPlaylistOpenMethodName
<< "' returned unexpected value:\n"
<< content;
throw XmlRpcMethodResponseException(eMsg.str());
}
XmlRpcValue innerContent = content[getPlaylistContentParamName];
// construct the SMIL file
Ptr<xmlpp::Document>::Ref
smilDocument(new xmlpp::Document(xmlVersion));
xmlpp::Element * smilRootNode
@ -1301,48 +1363,32 @@ WebStorageClient :: acquirePlaylist(Ptr<Playlist>::Ref oldPlaylist,
xmlpp::Element * smilParNode
= smilBodyNode->add_child(smilParNodeName);
Playlist::const_iterator it = oldPlaylist->begin();
if (result.hasMember(getPlaylistContentParamName)) {
content = result[getPlaylistContentParamName];
}
// if there is no content parameter, leave the original, empty content
index = 0;
// assume that it is as long as the size of the content array
while (it != oldPlaylist->end()) {
// we assume that the playlist is as long as the size of the content array
Playlist::const_iterator it = playlist->begin();
int index = 0;
while (it != playlist->end() && index < innerContent.size()) {
Ptr<PlaylistElement>::Ref plElement = it->second;
Ptr<time_duration>::Ref relativeOffset
= plElement->getRelativeOffset();
Ptr<FadeInfo>::Ref fadeInfo = plElement->getFadeInfo();
if (index >= content.size()) {
break;
}
XmlRpcValue contents = content[index];
++index;
if (!contents.hasMember(getPlaylistUrlParamName)) {
// TODO: maybe signal error?
continue;
}
XmlRpcValue contentElement = innerContent[index];
Ptr<Playable>::Ref playable;
Ptr<const std::string>::Ref url;
Ptr<AudioClip>::Ref audioClip;
Ptr<Playlist>::Ref playlist;
Ptr<UniqueId>::Ref subPlaylistId;
switch (plElement->getType()) {
case PlaylistElement::AudioClipType :
url.reset(new std::string(contents[getPlaylistUrlParamName]));
audioClip.reset(new AudioClip(*plElement->getAudioClip()));
audioClip->setUri(url);
url.reset();
newPlaylist->addPlayable(audioClip, relativeOffset, fadeInfo);
playable = audioClip;
url.reset(new std::string(
contentElement[getPlaylistUrlParamName]));
playable = plElement->getAudioClip();
break;
case PlaylistElement::PlaylistType :
playlist.reset(new Playlist(*plElement->getPlaylist()));
playlist = acquirePlaylist(playlist, contents);
newPlaylist->addPlayable(playlist, relativeOffset, fadeInfo);
playable = playlist;
subPlaylistId = plElement->getPlaylist()->getId();
playable = acquirePlaylist(subPlaylistId, contentElement);
url = playable->getUri();
plElement->setPlayable(playable);
break;
default : // this should never happen
throw XmlRpcInvalidArgumentException(
@ -1354,7 +1400,7 @@ WebStorageClient :: acquirePlaylist(Ptr<Playlist>::Ref oldPlaylist,
= smilParNode->add_child(smilPlayableNodeName);
smilPlayableNode->set_attribute(
smilPlayableUriAttrName,
*playable->getUri() );
*url );
smilPlayableNode->set_attribute(
smilRelativeOffsetAttrName,
*TimeConversion::timeDurationToSmilString(
@ -1430,19 +1476,20 @@ WebStorageClient :: acquirePlaylist(Ptr<Playlist>::Ref oldPlaylist,
smilAnimateFillAttrValue );
}
}
++it;
++it;
++index;
}
std::stringstream fileName;
fileName << localTempStorage << std::string(*newPlaylist->getId())
fileName << localTempStorage << std::string(*playlist->getId())
<< "-" << std::rand() << ".smil";
smilDocument->write_to_file_formatted(fileName.str(), "UTF-8");
Ptr<std::string>::Ref playlistUri(new std::string(fileName.str()));
newPlaylist->setUri(playlistUri);
playlist->setUri(playlistUri);
return newPlaylist;
return playlist;
}
@ -1452,11 +1499,91 @@ WebStorageClient :: acquirePlaylist(Ptr<Playlist>::Ref oldPlaylist,
void
WebStorageClient :: releasePlaylist(Ptr<Playlist>::Ref playlist) const
throw (Core::XmlRpcException)
{
if (playlist->getToken()) {
releasePlaylistFromServer(playlist);
}
releasePlaylistTempFile(playlist);
}
/*------------------------------------------------------------------------------
* Release a playlist, step 1: release access URLs at the storage server.
*----------------------------------------------------------------------------*/
void
WebStorageClient :: releasePlaylistFromServer(
Ptr<Playlist>::Ref playlist) const
throw (Core::XmlRpcException)
{
if (! playlist->getToken()) {
throw XmlRpcInvalidArgumentException("releasePlaylist() called without"
" acquirePlaylist()");
}
XmlRpcValue parameters;
XmlRpcValue result;
XmlRpcClient xmlRpcClient(storageServerName.c_str(), storageServerPort,
storageServerPath.c_str(), false);
parameters.clear();
parameters[getPlaylistTokenParamName] = std::string(
*playlist->getToken());
// TODO: remove the 'recursive' param from locstor.releasePlaylist because
// it is error-prone; should always use the same value as for accessPlaylist
parameters[getPlaylistRecursiveParamName] = true;
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(*playlist->getId())) {
std::stringstream eMsg;
eMsg << "Mismatched playlist ID from XML-RPC method '"
<< getPlaylistCloseMethodName
<< "': "
<< result[getPlaylistPlaylistIdParamName]
<< " instead of "
<< std::string(*playlist->getId())
<< ".";
// removed temporarily; see ticket #1468
// throw XmlRpcMethodResponseException(eMsg.str());
}
}
/*------------------------------------------------------------------------------
* Release a playlist, step 2: delete the temp file.
*----------------------------------------------------------------------------*/
void
WebStorageClient :: releasePlaylistTempFile(Ptr<Playlist>::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();
@ -1471,16 +1598,15 @@ WebStorageClient :: releasePlaylist(Ptr<Playlist>::Ref playlist) const
while (it != playlist->end()) {
Ptr<PlaylistElement>::Ref plElement = it->second;
if (plElement->getType() == PlaylistElement::AudioClipType) {
// don't have to release, as it will be done by the storage server
// for clips inside the playlist
// no temp file; nothing to do
++it;
} else if (plElement->getType() == PlaylistElement::PlaylistType) {
try {
releasePlaylist(it->second->getPlaylist());
releasePlaylistTempFile(it->second->getPlaylist());
}
catch (XmlRpcException &e) {
eMsg += e.what();
eMsg += "\n";
eMsg += '\n';
}
++it;
} else {

View file

@ -163,7 +163,8 @@ class WebStorageClient :
* @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.
* @param editToken pointer in which the token of the playlist is
* returned.
* @exception XmlRpcException if there is a problem with the XML-RPC
* call or no playlist with the specified
* id exists.
@ -172,50 +173,53 @@ class WebStorageClient :
editPlaylistGetUrl(Ptr<SessionId>::Ref sessionId,
Ptr<UniqueId>::Ref id,
Ptr<const std::string>::Ref& url,
Ptr<const std::string>::Ref& token)
Ptr<const std::string>::Ref& editToken)
throw (XmlRpcException);
/**
* Return a playlist with the specified id to be displayed.
* If the playlist is being edited, and this method is called
* by the same user who is editing the playlist,
* (i.e., the method is called with the same sessionId and playlistId
* that editPlaylist() was), then the working copy of the playlist
* is returned.
* Any other user gets the old (pre-editPlaylist()) copy from storage.
*
* @param sessionId the session ID from the authentication client
* @param id the id of the playlist to return.
* @param deep signal if all playable objects are to be accessed
* and locked, that are referenced by this playlist, or
* any playlist contained in this one.
* @return the requested playlist.
* @exception XmlRpcInvalidDataException if the audio clip we got
* from the storage is invalid.
* @exception XmlRpcException if there is a problem with the XML-RPC
* call or no playlist with the specified id exists.
*/
Ptr<Playlist>::Ref
getPlaylist(Ptr<SessionId>::Ref sessionId,
Ptr<UniqueId>::Ref id,
bool deep) const
throw (XmlRpcException);
/**
* Do the final stages of acquring a playlist: generate SMIL
* files, etc.
* Do the second step of acquring a playlist: generate the SMIL
* temp files.
*
* @param oldPlaylist the playlist to work on.
* @param result the XML-RPC result from getPlaylist() call
* with deep == true
* @param id the ID of the new playlist to be constructed
* @param content the XML-RPC result from locstor.accessPlaylist
* @return a playlist which has a URI filed, and all things below
* it are openned properly and processed as well.
* it are opened properly and processed as well.
* @exception XmlRpcException if there is a problem with the XML-RPC
* call or no playlist with the specified id exists.
*/
Ptr<Playlist>::Ref
acquirePlaylist(Ptr<Playlist>::Ref oldPlaylist,
XmlRpcValue & result) const
acquirePlaylist(Ptr<UniqueId>::Ref id,
XmlRpcValue & content) const
throw (XmlRpcException);
/**
* Execute the XML-RPC function call to release the playlist
* access URL at the storage server.
*
* This needs to be done for the outermost playlist only; the
* sub-playlists and audio clips contained inside are released
* recursively by the storage server automatically.
*
* @param playlist the playlist to release.
* @exception XmlRpcException if there is a problem with the XML-RPC
* call or the playlist has no token field
*/
void
releasePlaylistFromServer(Ptr<Playlist>::Ref playlist) const
throw (XmlRpcException);
/**
* Remove the temporary SMIL file created for the playlist.
*
* This needs to be done for every playlist, including sub-playlists
* contained inside other playlists.
*
* @param playlist the playlist to release.
* @exception XmlRpcException if there is a problem with the XML-RPC
* call or the playlist has no uri field
*/
void
releasePlaylistTempFile(Ptr<Playlist>::Ref playlist) const
throw (XmlRpcException);
@ -313,10 +317,7 @@ class WebStorageClient :
virtual Ptr<Playlist>::Ref
getPlaylist(Ptr<SessionId>::Ref sessionId,
Ptr<UniqueId>::Ref id) const
throw (XmlRpcException)
{
return getPlaylist(sessionId, id, false);
}
throw (XmlRpcException);
/**
* Return a playlist with the specified id to be edited.
@ -364,13 +365,13 @@ class WebStorageClient :
* the playlist (and lose all changes) at the next login using
* this method.
*
* @param playlistToken the token of the edited playlist
* @param editToken the token of the edited playlist
* @exception XmlRpcException if there is a problem with the XML-RPC
* call or no playlist with the specified
* token exists.
*/
virtual void
revertPlaylist(Ptr<const std::string>::Ref playlistToken)
revertPlaylist(Ptr<const std::string>::Ref editToken)
throw (XmlRpcException);
@ -401,12 +402,7 @@ class WebStorageClient :
virtual Ptr<Playlist>::Ref
acquirePlaylist(Ptr<SessionId>::Ref sessionId,
Ptr<UniqueId>::Ref id) const
throw (XmlRpcException)
{
// FIXME: silently, with deep == true, getPlaylist will also
// generate all related SMIL files, etc.
return getPlaylist(sessionId, id, true);
}
throw (XmlRpcException);
/**
* Release the resources (audio clips, other playlists) used

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" ?>
<playlist id="0000000000000001"
<playlist id="0000000000000002"
title="My Second Playlist"
playlength="00:00:29.700000" >
<playlistElement id="0000000000000101"

View file

@ -958,7 +958,7 @@ class XR_LocStor extends LocStor{
* inside playlist (default: false)</li>
* </ul>
*
* On success, returns a XML-RPC struct with single field:
* On success, returns an XML-RPC struct with the following fields:
* <ul>
* <li> url : string - readable url of accessed playlist in
* XML format</li>
@ -967,6 +967,11 @@ class XR_LocStor extends LocStor{
* <li> content: array of structs - recursive access (optional)</li>
* </ul>
*
* The <code>content</code> field contains a struct for each playlist
* element contained in the playlist. For audio clips, this struct is
* of type <code>{url, token}</code>; for sub-playlists, it is of type
* <code>{url, token, chsum, content}</code>.
*
* On errors, returns an XML-RPC error response.
* The possible error codes and error message are:
* <ul>