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:
parent
df31c8d72f
commit
37101d2166
9 changed files with 416 additions and 191 deletions
|
@ -156,6 +156,9 @@ class Playable : public boost::enable_shared_from_this<Playable>
|
||||||
* Return the token which is used to identify this audio clip
|
* Return the token which is used to identify this audio clip
|
||||||
* or playlist to the storage server.
|
* 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.
|
* @return the token.
|
||||||
*/
|
*/
|
||||||
virtual Ptr<const std::string>::Ref
|
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
|
* Set the token which is used to identify this audio clip
|
||||||
* or playlist to the storage server.
|
* 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.
|
* @param token a new token.
|
||||||
*/
|
*/
|
||||||
virtual void
|
virtual void
|
||||||
|
|
|
@ -127,6 +127,28 @@ using namespace boost::posix_time;
|
||||||
* <!ATTLIST playlist playlength NMTOKEN #IMPLIED >
|
* <!ATTLIST playlist playlength NMTOKEN #IMPLIED >
|
||||||
* </code></pre>
|
* </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$
|
* @author $Author$
|
||||||
* @version $Revision$
|
* @version $Revision$
|
||||||
*/
|
*/
|
||||||
|
@ -160,10 +182,17 @@ class Playlist : public Configurable,
|
||||||
Ptr<const std::string>::Ref uri;
|
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;
|
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
|
* A map type for storing the playlist elements associated with
|
||||||
* this playlist, indexed by their relative offsets.
|
* this playlist, indexed by their relative offsets.
|
||||||
|
@ -464,6 +493,9 @@ class Playlist : public Configurable,
|
||||||
* Return the token which is used to identify this
|
* Return the token which is used to identify this
|
||||||
* playlist to the storage server.
|
* 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.
|
* @return the token.
|
||||||
*/
|
*/
|
||||||
virtual Ptr<const std::string>::Ref
|
virtual Ptr<const std::string>::Ref
|
||||||
|
@ -476,6 +508,9 @@ class Playlist : public Configurable,
|
||||||
* Set the token which is used to identify this
|
* Set the token which is used to identify this
|
||||||
* playlist to the storage server.
|
* 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.
|
* @param token a new token.
|
||||||
*/
|
*/
|
||||||
virtual void
|
virtual void
|
||||||
|
@ -485,6 +520,37 @@ class Playlist : public Configurable,
|
||||||
this->token = token;
|
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.
|
* Test whether the playlist is locked for editing.
|
||||||
*
|
*
|
||||||
|
@ -493,7 +559,7 @@ class Playlist : public Configurable,
|
||||||
bool
|
bool
|
||||||
isLocked() const throw ()
|
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()
|
* Checks the type of the playlist, and calls either addAudioClip()
|
||||||
* or addPlaylist().
|
* or addPlaylist().
|
||||||
*
|
*
|
||||||
* @param audioClip the new playable item to be added
|
* @param playable the new playable item to be added
|
||||||
* @param relativeOffset the start of the playable item, relative
|
* @param relativeOffset the start of the playable item, relative
|
||||||
* to the start of the playlist
|
* to the start of the playlist
|
||||||
* @param fadeInfo the fade in / fade out info (optional)
|
* @param fadeInfo the fade in / fade out info (optional)
|
||||||
* @return the ID of the new PlaylistElement
|
* @return the ID of the new PlaylistElement
|
||||||
* @exception std::invalid_argument if playable is neither an AudioClip
|
* @exception std::invalid_argument if playable is neither an AudioClip
|
||||||
* nor a Playlist
|
* nor a Playlist
|
||||||
|
@ -711,7 +777,7 @@ class Playlist : public Configurable,
|
||||||
/**
|
/**
|
||||||
* Return a partial XML representation of this audio clip or playlist.
|
* 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 <playlist>
|
||||||
* XML element, with minimal information (ID, title, playlength)
|
* XML element, with minimal information (ID, title, playlength)
|
||||||
* only, without an XML header or any other metadata.
|
* 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.
|
* Return a complete XML representation of this playlist.
|
||||||
*
|
*
|
||||||
* This is a string containing a an XML document with a
|
* This is a string containing a an XML document with a
|
||||||
* <playlist> root node, together with an XML header and a
|
* <playlist> root node, together with an XML header and a
|
||||||
* <metadata> element (for the outermost playlist only).
|
* <metadata> element (for the outermost playlist only).
|
||||||
*
|
*
|
||||||
* The encoding is UTF-8. IDs are 16-digit hexadecimal numbers,
|
* The encoding is UTF-8. IDs are 16-digit hexadecimal numbers,
|
||||||
* time durations have the format "hh:mm:ss.ssssss".
|
* 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
|
* All other metadata fields in the audio clips and sub-playlists
|
||||||
* will be lost.
|
* will be lost.
|
||||||
*
|
*
|
||||||
* The <i>uri</i> and <i>token</i> fields are currently not part
|
* The <i>uri</i>, <i>token</i> and <i>editToken</i> fields are not
|
||||||
* of the XML document string returned.
|
* part of the XML document string returned.
|
||||||
*
|
*
|
||||||
* @return a string representation of the playlist as an XML document
|
* @return a string representation of the playlist as an XML document
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -203,6 +203,7 @@ class PlaylistElement : public Configurable
|
||||||
this->audioClip = audioClip;
|
this->audioClip = audioClip;
|
||||||
this->playable = audioClip;
|
this->playable = audioClip;
|
||||||
this->fadeInfo = fadeInfo;
|
this->fadeInfo = fadeInfo;
|
||||||
|
this->type = AudioClipType;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -351,6 +352,31 @@ class PlaylistElement : public Configurable
|
||||||
return playable;
|
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.
|
* Return the audio clip associated with the playlist element.
|
||||||
*
|
*
|
||||||
|
|
|
@ -346,7 +346,7 @@ TestStorageClient :: getPlaylist(Ptr<SessionId>::Ref sessionId,
|
||||||
EditedPlaylistsType::const_iterator
|
EditedPlaylistsType::const_iterator
|
||||||
editIt = editedPlaylists.find(id->getId());
|
editIt = editedPlaylists.find(id->getId());
|
||||||
if (editIt != editedPlaylists.end() // is being edited
|
if (editIt != editedPlaylists.end() // is being edited
|
||||||
&& (*editIt->second->getToken() == sessionId->getId())) { // by us
|
&& (*editIt->second->getEditToken() == sessionId->getId())) { // by us
|
||||||
playlist = editIt->second;
|
playlist = editIt->second;
|
||||||
} else {
|
} else {
|
||||||
PlaylistMapType::const_iterator
|
PlaylistMapType::const_iterator
|
||||||
|
@ -378,8 +378,8 @@ TestStorageClient :: editPlaylist(Ptr<SessionId>::Ref sessionId,
|
||||||
}
|
}
|
||||||
|
|
||||||
Ptr<Playlist>::Ref playlist = getPlaylist(sessionId, id);
|
Ptr<Playlist>::Ref playlist = getPlaylist(sessionId, id);
|
||||||
Ptr<std::string>::Ref token(new std::string(sessionId->getId()));
|
Ptr<std::string>::Ref editToken(new std::string(sessionId->getId()));
|
||||||
playlist->setToken(token);
|
playlist->setEditToken(editToken);
|
||||||
|
|
||||||
editedPlaylists[id->getId()] = playlist;
|
editedPlaylists[id->getId()] = playlist;
|
||||||
return playlist;
|
return playlist;
|
||||||
|
@ -398,11 +398,11 @@ TestStorageClient :: savePlaylist(Ptr<SessionId>::Ref sessionId,
|
||||||
throw XmlRpcException("missing session ID argument");
|
throw XmlRpcException("missing session ID argument");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! playlist->getToken()) {
|
if (! playlist->getEditToken()) {
|
||||||
throw XmlRpcException("savePlaylist() called without editPlaylist()");
|
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"
|
throw XmlRpcException("tried to save playlist in different session"
|
||||||
" than the one it was opened in???");
|
" than the one it was opened in???");
|
||||||
}
|
}
|
||||||
|
@ -411,12 +411,12 @@ TestStorageClient :: savePlaylist(Ptr<SessionId>::Ref sessionId,
|
||||||
editIt = editedPlaylists.find(playlist->getId()->getId());
|
editIt = editedPlaylists.find(playlist->getId()->getId());
|
||||||
|
|
||||||
if ((editIt == editedPlaylists.end())
|
if ((editIt == editedPlaylists.end())
|
||||||
|| (*playlist->getToken() != *editIt->second->getToken())) {
|
|| (*playlist->getEditToken() != *editIt->second->getEditToken())) {
|
||||||
throw XmlRpcException("savePlaylist() called without editPlaylist()");
|
throw XmlRpcException("savePlaylist() called without editPlaylist()");
|
||||||
}
|
}
|
||||||
|
|
||||||
Ptr<std::string>::Ref nullPointer;
|
Ptr<std::string>::Ref nullPointer;
|
||||||
playlist->setToken(nullPointer);
|
playlist->setEditToken(nullPointer);
|
||||||
|
|
||||||
PlaylistMapType::iterator
|
PlaylistMapType::iterator
|
||||||
storeIt = playlistMap.find(playlist->getId()->getId());
|
storeIt = playlistMap.find(playlist->getId()->getId());
|
||||||
|
@ -434,7 +434,7 @@ TestStorageClient :: savePlaylist(Ptr<SessionId>::Ref sessionId,
|
||||||
* Revert a playlist to its pre-editing state.
|
* Revert a playlist to its pre-editing state.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
void
|
||||||
TestStorageClient :: revertPlaylist(Ptr<const std::string>::Ref playlistToken)
|
TestStorageClient :: revertPlaylist(Ptr<const std::string>::Ref editToken)
|
||||||
throw (XmlRpcException)
|
throw (XmlRpcException)
|
||||||
{
|
{
|
||||||
std::cerr << "TestStorageClient :: revertPlaylist"
|
std::cerr << "TestStorageClient :: revertPlaylist"
|
||||||
|
|
|
@ -321,13 +321,13 @@ class TestStorageClient :
|
||||||
* the playlist (and lose all changes) at the next login using
|
* the playlist (and lose all changes) at the next login using
|
||||||
* this method.
|
* 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
|
* @exception XmlRpcException if there is a problem with the XML-RPC
|
||||||
* call or no playlist with the specified
|
* call or no playlist with the specified
|
||||||
* token exists.
|
* token exists.
|
||||||
*/
|
*/
|
||||||
virtual void
|
virtual void
|
||||||
revertPlaylist(Ptr<const std::string>::Ref playlistToken)
|
revertPlaylist(Ptr<const std::string>::Ref editToken)
|
||||||
throw (XmlRpcException);
|
throw (XmlRpcException);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -847,13 +847,13 @@ WebStorageClient :: createPlaylist(Ptr<SessionId>::Ref sessionId)
|
||||||
|
|
||||||
Ptr<time_duration>::Ref playlength(new time_duration(0,0,0,0));
|
Ptr<time_duration>::Ref playlength(new time_duration(0,0,0,0));
|
||||||
Ptr<Playlist>::Ref playlist(new Playlist(newId, playlength));
|
Ptr<Playlist>::Ref playlist(new Playlist(newId, playlength));
|
||||||
playlist->setToken(token);
|
playlist->setEditToken(token);
|
||||||
|
|
||||||
editedPlaylists[newId->getId()] = std::make_pair(sessionId, playlist);
|
editedPlaylists[newId->getId()] = std::make_pair(sessionId, playlist);
|
||||||
savePlaylist(sessionId, playlist);
|
savePlaylist(sessionId, playlist);
|
||||||
|
|
||||||
token.reset();
|
token.reset();
|
||||||
playlist->setToken(token);
|
playlist->setEditToken(token);
|
||||||
|
|
||||||
return playlist->getId();
|
return playlist->getId();
|
||||||
}
|
}
|
||||||
|
@ -918,9 +918,8 @@ WebStorageClient :: existsPlaylist(Ptr<SessionId>::Ref sessionId,
|
||||||
* Return a playlist to be displayed.
|
* Return a playlist to be displayed.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
Ptr<Playlist>::Ref
|
Ptr<Playlist>::Ref
|
||||||
WebStorageClient :: getPlaylist(Ptr<SessionId>::Ref sessionId,
|
WebStorageClient :: getPlaylist(Ptr<SessionId>::Ref sessionId,
|
||||||
Ptr<UniqueId>::Ref id,
|
Ptr<UniqueId>::Ref id) const
|
||||||
bool deep) const
|
|
||||||
throw (Core::XmlRpcException)
|
throw (Core::XmlRpcException)
|
||||||
{
|
{
|
||||||
EditedPlaylistsType::const_iterator
|
EditedPlaylistsType::const_iterator
|
||||||
|
@ -940,7 +939,7 @@ WebStorageClient :: getPlaylist(Ptr<SessionId>::Ref sessionId,
|
||||||
parameters.clear();
|
parameters.clear();
|
||||||
parameters[getPlaylistSessionIdParamName] = sessionId->getId();
|
parameters[getPlaylistSessionIdParamName] = sessionId->getId();
|
||||||
parameters[getPlaylistPlaylistIdParamName] = std::string(*id);
|
parameters[getPlaylistPlaylistIdParamName] = std::string(*id);
|
||||||
parameters[getPlaylistRecursiveParamName] = deep;
|
parameters[getPlaylistRecursiveParamName] = false;
|
||||||
|
|
||||||
result.clear();
|
result.clear();
|
||||||
if (!xmlRpcClient.execute(getPlaylistOpenMethodName.c_str(),
|
if (!xmlRpcClient.execute(getPlaylistOpenMethodName.c_str(),
|
||||||
|
@ -960,25 +959,33 @@ WebStorageClient :: getPlaylist(Ptr<SessionId>::Ref sessionId,
|
||||||
<< result;
|
<< result;
|
||||||
throw Core::XmlRpcMethodFaultException(eMsg.str());
|
throw Core::XmlRpcMethodFaultException(eMsg.str());
|
||||||
}
|
}
|
||||||
if (! result.hasMember(getPlaylistUrlParamName)
|
|
||||||
|| result[getPlaylistUrlParamName].getType()
|
if (! result.hasMember(getPlaylistTokenParamName)
|
||||||
!= XmlRpcValue::TypeString
|
|
||||||
|| ! result.hasMember(getPlaylistTokenParamName)
|
|
||||||
|| result[getPlaylistTokenParamName].getType()
|
|| result[getPlaylistTokenParamName].getType()
|
||||||
!= XmlRpcValue::TypeString) {
|
!= XmlRpcValue::TypeString) {
|
||||||
std::stringstream eMsg;
|
std::stringstream eMsg;
|
||||||
eMsg << "XML-RPC method '"
|
eMsg << "XML-RPC method '"
|
||||||
<< getPlaylistOpenMethodName
|
<< getPlaylistOpenMethodName
|
||||||
<< "' returned unexpected value:\n"
|
<< "' returned unexpected value:\n"
|
||||||
<< result;
|
<< result;
|
||||||
throw XmlRpcMethodResponseException(eMsg.str());
|
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 url = result[getPlaylistUrlParamName];
|
||||||
const std::string token = result[getPlaylistTokenParamName];
|
|
||||||
|
|
||||||
Ptr<Playlist>::Ref playlist(new Playlist(id));
|
|
||||||
|
|
||||||
|
Ptr<Playlist>::Ref playlist(new Playlist(id));
|
||||||
try {
|
try {
|
||||||
Ptr<xmlpp::DomParser>::Ref parser(new xmlpp::DomParser());
|
Ptr<xmlpp::DomParser>::Ref parser(new xmlpp::DomParser());
|
||||||
parser->parse_file(url);
|
parser->parse_file(url);
|
||||||
|
@ -994,47 +1001,9 @@ WebStorageClient :: getPlaylist(Ptr<SessionId>::Ref sessionId,
|
||||||
throw XmlRpcInvalidDataException(
|
throw XmlRpcInvalidDataException(
|
||||||
"error parsing playlist metafile");
|
"error parsing playlist metafile");
|
||||||
}
|
}
|
||||||
|
playlist->setToken(token);
|
||||||
|
|
||||||
if (deep) {
|
releasePlaylistFromServer(playlist);
|
||||||
playlist = acquirePlaylist(playlist, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
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 playlist;
|
||||||
}
|
}
|
||||||
|
@ -1053,9 +1022,9 @@ WebStorageClient :: editPlaylist(Ptr<SessionId>::Ref sessionId,
|
||||||
" being edited");
|
" 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));
|
Ptr<Playlist>::Ref playlist(new Playlist(id));
|
||||||
try {
|
try {
|
||||||
|
@ -1074,7 +1043,7 @@ WebStorageClient :: editPlaylist(Ptr<SessionId>::Ref sessionId,
|
||||||
"error parsing playlist metafile");
|
"error parsing playlist metafile");
|
||||||
}
|
}
|
||||||
|
|
||||||
playlist->setToken(token);
|
playlist->setEditToken(editToken);
|
||||||
editedPlaylists[id->getId()] = std::make_pair(sessionId, playlist);
|
editedPlaylists[id->getId()] = std::make_pair(sessionId, playlist);
|
||||||
|
|
||||||
return playlist;
|
return playlist;
|
||||||
|
@ -1088,7 +1057,7 @@ void
|
||||||
WebStorageClient :: editPlaylistGetUrl(Ptr<SessionId>::Ref sessionId,
|
WebStorageClient :: editPlaylistGetUrl(Ptr<SessionId>::Ref sessionId,
|
||||||
Ptr<UniqueId>::Ref id,
|
Ptr<UniqueId>::Ref id,
|
||||||
Ptr<const std::string>::Ref& url,
|
Ptr<const std::string>::Ref& url,
|
||||||
Ptr<const std::string>::Ref& token)
|
Ptr<const std::string>::Ref& editToken)
|
||||||
throw (Core::XmlRpcException)
|
throw (Core::XmlRpcException)
|
||||||
{
|
{
|
||||||
XmlRpcValue parameters;
|
XmlRpcValue parameters;
|
||||||
|
@ -1138,7 +1107,7 @@ WebStorageClient :: editPlaylistGetUrl(Ptr<SessionId>::Ref sessionId,
|
||||||
}
|
}
|
||||||
|
|
||||||
url.reset(new const std::string(result[getPlaylistUrlParamName]));
|
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)
|
Ptr<Playlist>::Ref playlist)
|
||||||
throw (Core::XmlRpcException)
|
throw (Core::XmlRpcException)
|
||||||
{
|
{
|
||||||
if (!playlist || !playlist->getToken()) {
|
if (!playlist || !playlist->getEditToken()) {
|
||||||
throw XmlRpcInvalidArgumentException("playlist has no token field");
|
throw XmlRpcInvalidArgumentException("playlist has no editToken field");
|
||||||
}
|
}
|
||||||
|
|
||||||
EditedPlaylistsType::iterator
|
EditedPlaylistsType::iterator
|
||||||
|
@ -1174,7 +1143,7 @@ WebStorageClient :: savePlaylist(Ptr<SessionId>::Ref sessionId,
|
||||||
parameters[savePlaylistSessionIdParamName]
|
parameters[savePlaylistSessionIdParamName]
|
||||||
= sessionId->getId();
|
= sessionId->getId();
|
||||||
parameters[savePlaylistTokenParamName]
|
parameters[savePlaylistTokenParamName]
|
||||||
= *playlist->getToken();
|
= *playlist->getEditToken();
|
||||||
parameters[savePlaylistNewPlaylistParamName]
|
parameters[savePlaylistNewPlaylistParamName]
|
||||||
= std::string(*playlist->getXmlDocumentString());
|
= std::string(*playlist->getXmlDocumentString());
|
||||||
|
|
||||||
|
@ -1212,7 +1181,7 @@ WebStorageClient :: savePlaylist(Ptr<SessionId>::Ref sessionId,
|
||||||
}
|
}
|
||||||
|
|
||||||
Ptr<const std::string>::Ref nullpointer;
|
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.
|
* Revert a playlist to its pre-editing state.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
void
|
||||||
WebStorageClient :: revertPlaylist(Ptr<const std::string>::Ref playlistToken)
|
WebStorageClient :: revertPlaylist(Ptr<const std::string>::Ref editToken)
|
||||||
throw (XmlRpcException)
|
throw (XmlRpcException)
|
||||||
{
|
{
|
||||||
if (!playlistToken) {
|
if (!editToken) {
|
||||||
throw XmlRpcInvalidArgumentException("null pointer in argument");
|
throw XmlRpcInvalidArgumentException("null pointer in argument");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1237,7 +1206,7 @@ WebStorageClient :: revertPlaylist(Ptr<const std::string>::Ref playlistToken)
|
||||||
parameters[revertPlaylistSessionIdParamName] // dummy parameter
|
parameters[revertPlaylistSessionIdParamName] // dummy parameter
|
||||||
= "";
|
= "";
|
||||||
parameters[revertPlaylistTokenParamName]
|
parameters[revertPlaylistTokenParamName]
|
||||||
= *playlistToken;
|
= *editToken;
|
||||||
|
|
||||||
result.clear();
|
result.clear();
|
||||||
if (!xmlRpcClient.execute(revertPlaylistMethodName.c_str(),
|
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
|
Ptr<Playlist>::Ref
|
||||||
WebStorageClient :: acquirePlaylist(Ptr<Playlist>::Ref oldPlaylist,
|
WebStorageClient :: acquirePlaylist(Ptr<SessionId>::Ref sessionId,
|
||||||
XmlRpcValue & result) const
|
Ptr<UniqueId>::Ref id) const
|
||||||
throw (Core::XmlRpcException)
|
throw (Core::XmlRpcException)
|
||||||
{
|
{
|
||||||
XmlRpcValue content;
|
XmlRpcValue parameters;
|
||||||
int index;
|
XmlRpcValue result;
|
||||||
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
|
|
||||||
|
|
||||||
|
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
|
Ptr<xmlpp::Document>::Ref
|
||||||
smilDocument(new xmlpp::Document(xmlVersion));
|
smilDocument(new xmlpp::Document(xmlVersion));
|
||||||
xmlpp::Element * smilRootNode
|
xmlpp::Element * smilRootNode
|
||||||
|
@ -1301,48 +1363,32 @@ WebStorageClient :: acquirePlaylist(Ptr<Playlist>::Ref oldPlaylist,
|
||||||
xmlpp::Element * smilParNode
|
xmlpp::Element * smilParNode
|
||||||
= smilBodyNode->add_child(smilParNodeName);
|
= smilBodyNode->add_child(smilParNodeName);
|
||||||
|
|
||||||
Playlist::const_iterator it = oldPlaylist->begin();
|
// we assume that the playlist is as long as the size of the content array
|
||||||
if (result.hasMember(getPlaylistContentParamName)) {
|
Playlist::const_iterator it = playlist->begin();
|
||||||
content = result[getPlaylistContentParamName];
|
int index = 0;
|
||||||
}
|
while (it != playlist->end() && index < innerContent.size()) {
|
||||||
// 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()) {
|
|
||||||
Ptr<PlaylistElement>::Ref plElement = it->second;
|
Ptr<PlaylistElement>::Ref plElement = it->second;
|
||||||
Ptr<time_duration>::Ref relativeOffset
|
Ptr<time_duration>::Ref relativeOffset
|
||||||
= plElement->getRelativeOffset();
|
= plElement->getRelativeOffset();
|
||||||
Ptr<FadeInfo>::Ref fadeInfo = plElement->getFadeInfo();
|
Ptr<FadeInfo>::Ref fadeInfo = plElement->getFadeInfo();
|
||||||
|
|
||||||
if (index >= content.size()) {
|
XmlRpcValue contentElement = innerContent[index];
|
||||||
break;
|
|
||||||
}
|
|
||||||
XmlRpcValue contents = content[index];
|
|
||||||
++index;
|
|
||||||
if (!contents.hasMember(getPlaylistUrlParamName)) {
|
|
||||||
// TODO: maybe signal error?
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ptr<Playable>::Ref playable;
|
Ptr<Playable>::Ref playable;
|
||||||
Ptr<const std::string>::Ref url;
|
Ptr<const std::string>::Ref url;
|
||||||
Ptr<AudioClip>::Ref audioClip;
|
Ptr<UniqueId>::Ref subPlaylistId;
|
||||||
Ptr<Playlist>::Ref playlist;
|
|
||||||
switch (plElement->getType()) {
|
switch (plElement->getType()) {
|
||||||
case PlaylistElement::AudioClipType :
|
case PlaylistElement::AudioClipType :
|
||||||
url.reset(new std::string(contents[getPlaylistUrlParamName]));
|
url.reset(new std::string(
|
||||||
audioClip.reset(new AudioClip(*plElement->getAudioClip()));
|
contentElement[getPlaylistUrlParamName]));
|
||||||
audioClip->setUri(url);
|
playable = plElement->getAudioClip();
|
||||||
url.reset();
|
|
||||||
newPlaylist->addPlayable(audioClip, relativeOffset, fadeInfo);
|
|
||||||
playable = audioClip;
|
|
||||||
break;
|
break;
|
||||||
case PlaylistElement::PlaylistType :
|
case PlaylistElement::PlaylistType :
|
||||||
playlist.reset(new Playlist(*plElement->getPlaylist()));
|
subPlaylistId = plElement->getPlaylist()->getId();
|
||||||
playlist = acquirePlaylist(playlist, contents);
|
playable = acquirePlaylist(subPlaylistId, contentElement);
|
||||||
newPlaylist->addPlayable(playlist, relativeOffset, fadeInfo);
|
url = playable->getUri();
|
||||||
playable = playlist;
|
plElement->setPlayable(playable);
|
||||||
break;
|
break;
|
||||||
default : // this should never happen
|
default : // this should never happen
|
||||||
throw XmlRpcInvalidArgumentException(
|
throw XmlRpcInvalidArgumentException(
|
||||||
|
@ -1354,7 +1400,7 @@ WebStorageClient :: acquirePlaylist(Ptr<Playlist>::Ref oldPlaylist,
|
||||||
= smilParNode->add_child(smilPlayableNodeName);
|
= smilParNode->add_child(smilPlayableNodeName);
|
||||||
smilPlayableNode->set_attribute(
|
smilPlayableNode->set_attribute(
|
||||||
smilPlayableUriAttrName,
|
smilPlayableUriAttrName,
|
||||||
*playable->getUri() );
|
*url );
|
||||||
smilPlayableNode->set_attribute(
|
smilPlayableNode->set_attribute(
|
||||||
smilRelativeOffsetAttrName,
|
smilRelativeOffsetAttrName,
|
||||||
*TimeConversion::timeDurationToSmilString(
|
*TimeConversion::timeDurationToSmilString(
|
||||||
|
@ -1431,18 +1477,19 @@ WebStorageClient :: acquirePlaylist(Ptr<Playlist>::Ref oldPlaylist,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
++it;
|
++it;
|
||||||
|
++index;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::stringstream fileName;
|
std::stringstream fileName;
|
||||||
fileName << localTempStorage << std::string(*newPlaylist->getId())
|
fileName << localTempStorage << std::string(*playlist->getId())
|
||||||
<< "-" << std::rand() << ".smil";
|
<< "-" << std::rand() << ".smil";
|
||||||
|
|
||||||
smilDocument->write_to_file_formatted(fileName.str(), "UTF-8");
|
smilDocument->write_to_file_formatted(fileName.str(), "UTF-8");
|
||||||
|
|
||||||
Ptr<std::string>::Ref playlistUri(new std::string(fileName.str()));
|
Ptr<std::string>::Ref playlistUri(new std::string(fileName.str()));
|
||||||
newPlaylist->setUri(playlistUri);
|
playlist->setUri(playlistUri);
|
||||||
|
|
||||||
return newPlaylist;
|
return playlist;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1452,6 +1499,86 @@ WebStorageClient :: acquirePlaylist(Ptr<Playlist>::Ref oldPlaylist,
|
||||||
void
|
void
|
||||||
WebStorageClient :: releasePlaylist(Ptr<Playlist>::Ref playlist) const
|
WebStorageClient :: releasePlaylist(Ptr<Playlist>::Ref playlist) const
|
||||||
throw (Core::XmlRpcException)
|
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()) {
|
if (! playlist->getUri()) {
|
||||||
throw XmlRpcInvalidArgumentException("playlist URI not found");
|
throw XmlRpcInvalidArgumentException("playlist URI not found");
|
||||||
|
@ -1471,16 +1598,15 @@ WebStorageClient :: releasePlaylist(Ptr<Playlist>::Ref playlist) const
|
||||||
while (it != playlist->end()) {
|
while (it != playlist->end()) {
|
||||||
Ptr<PlaylistElement>::Ref plElement = it->second;
|
Ptr<PlaylistElement>::Ref plElement = it->second;
|
||||||
if (plElement->getType() == PlaylistElement::AudioClipType) {
|
if (plElement->getType() == PlaylistElement::AudioClipType) {
|
||||||
// don't have to release, as it will be done by the storage server
|
// no temp file; nothing to do
|
||||||
// for clips inside the playlist
|
|
||||||
++it;
|
++it;
|
||||||
} else if (plElement->getType() == PlaylistElement::PlaylistType) {
|
} else if (plElement->getType() == PlaylistElement::PlaylistType) {
|
||||||
try {
|
try {
|
||||||
releasePlaylist(it->second->getPlaylist());
|
releasePlaylistTempFile(it->second->getPlaylist());
|
||||||
}
|
}
|
||||||
catch (XmlRpcException &e) {
|
catch (XmlRpcException &e) {
|
||||||
eMsg += e.what();
|
eMsg += e.what();
|
||||||
eMsg += "\n";
|
eMsg += '\n';
|
||||||
}
|
}
|
||||||
++it;
|
++it;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -163,7 +163,8 @@ class WebStorageClient :
|
||||||
* @param sessionId the session ID from the authentication client
|
* @param sessionId the session ID from the authentication client
|
||||||
* @param id the id of the playlist to return.
|
* @param id the id of the playlist to return.
|
||||||
* @param url pointer in which the URL of the playlist is returned.
|
* @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
|
* @exception XmlRpcException if there is a problem with the XML-RPC
|
||||||
* call or no playlist with the specified
|
* call or no playlist with the specified
|
||||||
* id exists.
|
* id exists.
|
||||||
|
@ -172,50 +173,53 @@ class WebStorageClient :
|
||||||
editPlaylistGetUrl(Ptr<SessionId>::Ref sessionId,
|
editPlaylistGetUrl(Ptr<SessionId>::Ref sessionId,
|
||||||
Ptr<UniqueId>::Ref id,
|
Ptr<UniqueId>::Ref id,
|
||||||
Ptr<const std::string>::Ref& url,
|
Ptr<const std::string>::Ref& url,
|
||||||
Ptr<const std::string>::Ref& token)
|
Ptr<const std::string>::Ref& editToken)
|
||||||
throw (XmlRpcException);
|
throw (XmlRpcException);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a playlist with the specified id to be displayed.
|
* Do the second step of acquring a playlist: generate the SMIL
|
||||||
* If the playlist is being edited, and this method is called
|
* temp files.
|
||||||
* 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 new playlist to be constructed
|
||||||
* @param id the id of the playlist to return.
|
* @param content the XML-RPC result from locstor.accessPlaylist
|
||||||
* @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.
|
|
||||||
*
|
|
||||||
* @param oldPlaylist the playlist to work on.
|
|
||||||
* @param result the XML-RPC result from getPlaylist() call
|
|
||||||
* with deep == true
|
|
||||||
* @return a playlist which has a URI filed, and all things below
|
* @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
|
* @exception XmlRpcException if there is a problem with the XML-RPC
|
||||||
* call or no playlist with the specified id exists.
|
* call or no playlist with the specified id exists.
|
||||||
*/
|
*/
|
||||||
Ptr<Playlist>::Ref
|
Ptr<Playlist>::Ref
|
||||||
acquirePlaylist(Ptr<Playlist>::Ref oldPlaylist,
|
acquirePlaylist(Ptr<UniqueId>::Ref id,
|
||||||
XmlRpcValue & result) const
|
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);
|
throw (XmlRpcException);
|
||||||
|
|
||||||
|
|
||||||
|
@ -313,10 +317,7 @@ class WebStorageClient :
|
||||||
virtual Ptr<Playlist>::Ref
|
virtual Ptr<Playlist>::Ref
|
||||||
getPlaylist(Ptr<SessionId>::Ref sessionId,
|
getPlaylist(Ptr<SessionId>::Ref sessionId,
|
||||||
Ptr<UniqueId>::Ref id) const
|
Ptr<UniqueId>::Ref id) const
|
||||||
throw (XmlRpcException)
|
throw (XmlRpcException);
|
||||||
{
|
|
||||||
return getPlaylist(sessionId, id, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a playlist with the specified id to be edited.
|
* 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
|
* the playlist (and lose all changes) at the next login using
|
||||||
* this method.
|
* 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
|
* @exception XmlRpcException if there is a problem with the XML-RPC
|
||||||
* call or no playlist with the specified
|
* call or no playlist with the specified
|
||||||
* token exists.
|
* token exists.
|
||||||
*/
|
*/
|
||||||
virtual void
|
virtual void
|
||||||
revertPlaylist(Ptr<const std::string>::Ref playlistToken)
|
revertPlaylist(Ptr<const std::string>::Ref editToken)
|
||||||
throw (XmlRpcException);
|
throw (XmlRpcException);
|
||||||
|
|
||||||
|
|
||||||
|
@ -401,12 +402,7 @@ class WebStorageClient :
|
||||||
virtual Ptr<Playlist>::Ref
|
virtual Ptr<Playlist>::Ref
|
||||||
acquirePlaylist(Ptr<SessionId>::Ref sessionId,
|
acquirePlaylist(Ptr<SessionId>::Ref sessionId,
|
||||||
Ptr<UniqueId>::Ref id) const
|
Ptr<UniqueId>::Ref id) const
|
||||||
throw (XmlRpcException)
|
throw (XmlRpcException);
|
||||||
{
|
|
||||||
// FIXME: silently, with deep == true, getPlaylist will also
|
|
||||||
// generate all related SMIL files, etc.
|
|
||||||
return getPlaylist(sessionId, id, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Release the resources (audio clips, other playlists) used
|
* Release the resources (audio clips, other playlists) used
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8" ?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<playlist id="0000000000000001"
|
<playlist id="0000000000000002"
|
||||||
title="My Second Playlist"
|
title="My Second Playlist"
|
||||||
playlength="00:00:29.700000" >
|
playlength="00:00:29.700000" >
|
||||||
<playlistElement id="0000000000000101"
|
<playlistElement id="0000000000000101"
|
||||||
|
|
|
@ -958,7 +958,7 @@ class XR_LocStor extends LocStor{
|
||||||
* inside playlist (default: false)</li>
|
* inside playlist (default: false)</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* On success, returns a XML-RPC struct with single field:
|
* On success, returns an XML-RPC struct with the following fields:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li> url : string - readable url of accessed playlist in
|
* <li> url : string - readable url of accessed playlist in
|
||||||
* XML format</li>
|
* XML format</li>
|
||||||
|
@ -967,6 +967,11 @@ class XR_LocStor extends LocStor{
|
||||||
* <li> content: array of structs - recursive access (optional)</li>
|
* <li> content: array of structs - recursive access (optional)</li>
|
||||||
* </ul>
|
* </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.
|
* On errors, returns an XML-RPC error response.
|
||||||
* The possible error codes and error message are:
|
* The possible error codes and error message are:
|
||||||
* <ul>
|
* <ul>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue