From 892d7d132fa10ea79bc4de194405781509308c2a Mon Sep 17 00:00:00 2001
From: fgerlits <fgerlits@cfc7b370-4200-0410-a6e3-cb6bdb053afe>
Date: Mon, 7 Feb 2005 21:35:21 +0000
Subject: [PATCH] added 7 scheduler methods to schedulerClient

---
 .../include/LiveSupport/Core/XmlRpcTools.h    |  60 ++-
 livesupport/modules/core/src/XmlRpcTools.cxx  |  95 ++++-
 .../modules/core/src/XmlRpcToolsTest.cxx      |  51 +--
 .../modules/schedulerClient/etc/Makefile.in   |  11 +-
 .../SchedulerClientInterface.h                | 124 +++++-
 .../src/SchedulerDaemonXmlRpcClient.cxx       | 383 ++++++++++++++++--
 .../src/SchedulerDaemonXmlRpcClient.h         | 106 ++++-
 .../src/SchedulerDaemonXmlRpcClientTest.cxx   | 123 ++++--
 .../src/SchedulerDaemonXmlRpcClientTest.h     |  22 +-
 .../scheduler/src/GetSchedulerTimeMethod.h    |   8 +-
 .../scheduler/src/UploadPlaylistMethod.h      |  10 +-
 11 files changed, 859 insertions(+), 134 deletions(-)

diff --git a/livesupport/modules/core/include/LiveSupport/Core/XmlRpcTools.h b/livesupport/modules/core/include/LiveSupport/Core/XmlRpcTools.h
index 2512c88a7..b387889d1 100644
--- a/livesupport/modules/core/include/LiveSupport/Core/XmlRpcTools.h
+++ b/livesupport/modules/core/include/LiveSupport/Core/XmlRpcTools.h
@@ -22,7 +22,7 @@
  
  
     Author   : $Author: fgerlits $
-    Version  : $Revision: 1.4 $
+    Version  : $Revision: 1.5 $
     Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/include/LiveSupport/Core/XmlRpcTools.h,v $
 
 ------------------------------------------------------------------------------*/
@@ -74,7 +74,7 @@ using namespace LiveSupport::Core;
  *  in the Scheduler.
  *
  *  @author  $Author: fgerlits $
- *  @version $Revision: 1.4 $
+ *  @version $Revision: 1.5 $
  */
 class XmlRpcTools
 {
@@ -227,6 +227,46 @@ class XmlRpcTools
             XmlRpc::XmlRpcValue                             & returnValue)
                                                                      throw ();
 
+        /**
+         *  Extract a Playlist from an XML-RPC parameter.
+         *
+         *  @param xmlRpcValue the XML-RPC parameter to extract from.
+         *  @return the extracted Playlist.
+         */
+        static Ptr<Playlist>::Ref
+        extractPlaylist(XmlRpc::XmlRpcValue    & xmlRpcValue)
+                                                throw (std::invalid_argument);
+
+        /**
+         *  Extract a vector of Playlists from an XML-RPC parameter.
+         *
+         *  @param xmlRpcValue the XML-RPC parameter to extract from.
+         *  @return a list of Playlists.
+         */
+        static Ptr<std::vector<Ptr<Playlist>::Ref> >::Ref
+        extractPlaylistVector(XmlRpc::XmlRpcValue   & xmlRpcValue)
+                                                throw (std::invalid_argument);
+
+        /**
+         *  Extract an AudioClip from an XML-RPC parameter.
+         *
+         *  @param xmlRpcValue the XML-RPC parameter to extract from.
+         *  @return the extracted AudioClip.
+         */
+        static Ptr<AudioClip>::Ref
+        extractAudioClip(XmlRpc::XmlRpcValue    & xmlRpcValue)
+                                                throw (std::invalid_argument);
+
+        /**
+         *  Extract a vector of AudioClips from an XML-RPC parameter.
+         *
+         *  @param xmlRpcValue the XML-RPC parameter to extract from.
+         *  @return a list of AudioClips.
+         */
+        static Ptr<std::vector<Ptr<AudioClip>::Ref> >::Ref
+        extractAudioClipVector(XmlRpc::XmlRpcValue   & xmlRpcValue)
+                                                throw (std::invalid_argument);
+
         /**
          *  Convert an error code, message pair to an XML-RPC fault response.
          *  This is done by throwing an XmlRpc::XmlRpcException.  The client
@@ -417,7 +457,7 @@ class XmlRpcTools
                 XmlRpc::XmlRpcValue     & returnValue)              throw ();
 
         /**
-         *  Add a playlist id to an XmlRpcValue
+         *  Add a playlist ID to an XmlRpcValue
          *
          *  @param playlistId the playlist ID to add to the XmlRpcValue
          *  @param returnValue an output parameter, which has the 
@@ -429,7 +469,19 @@ class XmlRpcTools
                 XmlRpc::XmlRpcValue     & returnValue)              throw ();
 
         /**
-         *  Add a playlist element id to an XmlRpcValue
+         *  Add an audio clip ID to an XmlRpcValue
+         *
+         *  @param audioClipId the audio clip ID to add to the XmlRpcValue
+         *  @param returnValue an output parameter, which has the 
+         *         audio clip ID added after the function returns.
+         */
+        static void
+        audioClipIdToXmlRpcValue(
+                Ptr<const UniqueId>::Ref  audioClipId,
+                XmlRpc::XmlRpcValue     & returnValue)              throw ();
+
+        /**
+         *  Add a playlist element ID to an XmlRpcValue
          *
          *  @param playlistElementId the playlist element ID 
          *                           to add to the XmlRpcValue
diff --git a/livesupport/modules/core/src/XmlRpcTools.cxx b/livesupport/modules/core/src/XmlRpcTools.cxx
index 231dd7827..d3dc76567 100644
--- a/livesupport/modules/core/src/XmlRpcTools.cxx
+++ b/livesupport/modules/core/src/XmlRpcTools.cxx
@@ -22,7 +22,7 @@
  
  
     Author   : $Author: fgerlits $
-    Version  : $Revision: 1.5 $
+    Version  : $Revision: 1.6 $
     Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/src/XmlRpcTools.cxx,v $
 
 ------------------------------------------------------------------------------*/
@@ -64,16 +64,16 @@ static const std::string idName = "id";
  *----------------------------------------------------------------------------*/
 static const std::string playlistIdName = "playlistId";
 
-/*------------------------------------------------------------------------------
- *  The name of the playlist element ID member in the XML-RPC param structure
- *----------------------------------------------------------------------------*/
-static const std::string playlistElementIdName = "playlistElementId";
-
 /*------------------------------------------------------------------------------
  *  The name of the audio clip ID member in the XML-RPC parameter structure
  *----------------------------------------------------------------------------*/
 static const std::string audioClipIdName = "audioClipId";
 
+/*------------------------------------------------------------------------------
+ *  The name of the playlist element ID member in the XML-RPC param structure
+ *----------------------------------------------------------------------------*/
+static const std::string playlistElementIdName = "playlistElementId";
+
 /*------------------------------------------------------------------------------
  *  The name of the relative offset member in the XML-RPC parameter structure
  *----------------------------------------------------------------------------*/
@@ -339,6 +339,76 @@ XmlRpcTools :: audioClipVectorToXmlRpcValue(
 }
 
 
+/*------------------------------------------------------------------------------
+ *  Extract a Playlist from an XML-RPC parameter.
+ *----------------------------------------------------------------------------*/
+Ptr<Playlist>::Ref
+XmlRpcTools :: extractPlaylist(XmlRpc::XmlRpcValue & xmlRpcValue)
+                                                throw (std::invalid_argument)
+{
+    Ptr<Playlist>::Ref  playlist(new Playlist(xmlRpcValue));
+                                         // may throw std::invalid_argument
+    return playlist;
+}
+
+
+/*------------------------------------------------------------------------------
+ *  Extract a vector of Playlists from an XML-RPC parameter.
+ *----------------------------------------------------------------------------*/
+Ptr<std::vector<Ptr<Playlist>::Ref> >::Ref
+XmlRpcTools :: extractPlaylistVector(XmlRpc::XmlRpcValue & xmlRpcValue)
+                                                throw (std::invalid_argument)
+{
+    if (xmlRpcValue.getType() != XmlRpc::XmlRpcValue::TypeArray) {
+        throw std::invalid_argument("argument to extractPlaylistVector "
+                                    "is not an array");
+    }
+
+    Ptr<std::vector<Ptr<Playlist>::Ref> >::Ref  playlistVector;
+    for (int i=0; i < xmlRpcValue.size(); i++) {
+        Ptr<Playlist>::Ref  playlist(new Playlist(xmlRpcValue[i]));
+                                         // may throw std::invalid_argument
+        playlistVector->push_back(playlist);
+    }
+    return playlistVector;
+}
+
+
+/*------------------------------------------------------------------------------
+ *  Extract an AudioClip from an XML-RPC parameter.
+ *----------------------------------------------------------------------------*/
+Ptr<AudioClip>::Ref
+XmlRpcTools :: extractAudioClip(XmlRpc::XmlRpcValue & xmlRpcValue)
+                                                throw (std::invalid_argument)
+{
+    Ptr<AudioClip>::Ref  audioClip(new AudioClip(xmlRpcValue));
+                                         // may throw std::invalid_argument
+    return audioClip;
+}
+
+
+/*------------------------------------------------------------------------------
+ *  Extract a vector of AudioClips from an XML-RPC parameter.
+ *----------------------------------------------------------------------------*/
+Ptr<std::vector<Ptr<AudioClip>::Ref> >::Ref
+XmlRpcTools :: extractAudioClipVector(XmlRpc::XmlRpcValue & xmlRpcValue)
+                                                throw (std::invalid_argument)
+{
+    if (xmlRpcValue.getType() != XmlRpc::XmlRpcValue::TypeArray) {
+        throw std::invalid_argument("argument to extractAudioClipVector "
+                                    "is not an array");
+    }
+
+    Ptr<std::vector<Ptr<AudioClip>::Ref> >::Ref  audioClipVector;
+    for (int i=0; i < xmlRpcValue.size(); i++) {
+        Ptr<AudioClip>::Ref  audioClip(new AudioClip(xmlRpcValue[i]));
+                                         // may throw std::invalid_argument
+        audioClipVector->push_back(audioClip);
+    }
+    return audioClipVector;
+}
+
+
 /*------------------------------------------------------------------------------
  *  Convert an error code, error message pair to an XML-RPC fault response
  *----------------------------------------------------------------------------*/
@@ -627,6 +697,19 @@ XmlRpcTools :: playlistIdToXmlRpcValue(
 }
 
 
+/*------------------------------------------------------------------------------
+ *  Add an audio clip ID to an XmlRpcValue
+ *----------------------------------------------------------------------------*/
+void
+XmlRpcTools :: audioClipIdToXmlRpcValue(
+                            Ptr<const UniqueId>::Ref    audioClipId,
+                            XmlRpc::XmlRpcValue       & returnValue)
+                                                throw ()
+{
+    returnValue[audioClipIdName] = std::string(*audioClipId);
+}
+
+
 /*------------------------------------------------------------------------------
  *  Add a playlist element ID to an XmlRpcValue
  *----------------------------------------------------------------------------*/
diff --git a/livesupport/modules/core/src/XmlRpcToolsTest.cxx b/livesupport/modules/core/src/XmlRpcToolsTest.cxx
index 6faec94f5..c999ba1e3 100644
--- a/livesupport/modules/core/src/XmlRpcToolsTest.cxx
+++ b/livesupport/modules/core/src/XmlRpcToolsTest.cxx
@@ -22,7 +22,7 @@
  
  
     Author   : $Author: fgerlits $
-    Version  : $Revision: 1.4 $
+    Version  : $Revision: 1.5 $
     Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/src/XmlRpcToolsTest.cxx,v $
 
 ------------------------------------------------------------------------------*/
@@ -137,37 +137,10 @@ XmlRpcToolsTest :: firstTest(void)
     CPPUNIT_ASSERT(xmlRpcPlaylist["playlist"].getType() 
                                                 == XmlRpcValue::TypeString);
 
-    Ptr<Playlist>::Ref  copyOfPlaylist(new Playlist());
-    xmlpp::DomParser    parser;
-    CPPUNIT_ASSERT_NO_THROW(parser.parse_memory(std::string(
-                                        xmlRpcPlaylist["playlist"] )));
-    xmlpp::Element*     configElement = 0;
-    CPPUNIT_ASSERT_NO_THROW(configElement = parser.get_document()
-                                                 ->get_root_node());
-    CPPUNIT_ASSERT(configElement);
-    CPPUNIT_ASSERT_NO_THROW(copyOfPlaylist->configure(*configElement));
-
-    CPPUNIT_ASSERT(*copyOfPlaylist->getId()     == *playlist->getId());
-    CPPUNIT_ASSERT(*copyOfPlaylist->getTitle()  == *playlist->getTitle());
-    CPPUNIT_ASSERT(*copyOfPlaylist->getPlaylength() 
-                                           == *playlist->getPlaylength());
-
     CPPUNIT_ASSERT(xmlRpcAudioClip.hasMember("audioClip"));
     CPPUNIT_ASSERT(xmlRpcAudioClip["audioClip"].getType() 
                                                 == XmlRpcValue::TypeString);
 
-    Ptr<AudioClip>::Ref copyOfAudioClip(new AudioClip());
-    CPPUNIT_ASSERT_NO_THROW(parser.parse_memory(std::string(
-                                        xmlRpcAudioClip["audioClip"] )));
-    CPPUNIT_ASSERT_NO_THROW(configElement = parser.get_document()
-                                                 ->get_root_node());
-    CPPUNIT_ASSERT_NO_THROW(copyOfAudioClip->configure(*configElement));
-
-    CPPUNIT_ASSERT(*copyOfAudioClip->getId()     == *audioClip->getId());
-    CPPUNIT_ASSERT(*copyOfAudioClip->getTitle()  == *audioClip->getTitle());
-    CPPUNIT_ASSERT(*copyOfAudioClip->getPlaylength() 
-                                           == *audioClip->getPlaylength());
-
     XmlRpcValue              xmlRpcPlaylistId;
     Ptr<UniqueId>::Ref       playlistId(new UniqueId(rand()));
     Ptr<UniqueId>::Ref       audioClipId(new UniqueId(rand()));
@@ -181,10 +154,16 @@ XmlRpcToolsTest :: firstTest(void)
     Ptr<UniqueId>::Ref       newPlaylistId;
     Ptr<UniqueId>::Ref       newAudioClipId;
     Ptr<time_duration>::Ref  newRelativeOffset;
+    Ptr<Playlist>::Ref       newPlaylist;
+    Ptr<AudioClip>::Ref      newAudioClip;
     try {
-       newPlaylistId     = XmlRpcTools::extractPlaylistId(xmlRpcPlaylistId);
-       newAudioClipId    = XmlRpcTools::extractAudioClipId(xmlRpcPlaylistId);
-       newRelativeOffset = XmlRpcTools::extractRelativeOffset(xmlRpcPlaylistId);
+        newPlaylistId   = XmlRpcTools::extractPlaylistId(xmlRpcPlaylistId);
+        newAudioClipId  = XmlRpcTools::extractAudioClipId(xmlRpcPlaylistId);
+        newRelativeOffset 
+                        = XmlRpcTools::extractRelativeOffset(xmlRpcPlaylistId);
+        newPlaylist     = XmlRpcTools::extractPlaylist(xmlRpcPlaylist);
+        newAudioClip    = XmlRpcTools::extractAudioClip(xmlRpcAudioClip);
+        
     } catch (std::invalid_argument &e) {
         CPPUNIT_FAIL(e.what());
     }
@@ -192,6 +171,16 @@ XmlRpcToolsTest :: firstTest(void)
     CPPUNIT_ASSERT(*playlistId     == *newPlaylistId);
     CPPUNIT_ASSERT(*audioClipId    == *newAudioClipId);
     CPPUNIT_ASSERT(*relativeOffset == *newRelativeOffset);
+
+    CPPUNIT_ASSERT(*playlist->getId()     == *newPlaylist->getId());
+    CPPUNIT_ASSERT(*playlist->getTitle()  == *newPlaylist->getTitle());
+    CPPUNIT_ASSERT(*playlist->getPlaylength() 
+                                          == *newPlaylist->getPlaylength());
+
+    CPPUNIT_ASSERT(*audioClip->getId()     == *newAudioClip->getId());
+    CPPUNIT_ASSERT(*audioClip->getTitle()  == *newAudioClip->getTitle());
+    CPPUNIT_ASSERT(*audioClip->getPlaylength() 
+                                           == *newAudioClip->getPlaylength());
 }
 
 
diff --git a/livesupport/modules/schedulerClient/etc/Makefile.in b/livesupport/modules/schedulerClient/etc/Makefile.in
index 0aaee6131..ff9c44b2f 100644
--- a/livesupport/modules/schedulerClient/etc/Makefile.in
+++ b/livesupport/modules/schedulerClient/etc/Makefile.in
@@ -20,8 +20,8 @@
 #   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 #
 #
-#   Author   : $Author: maroy $
-#   Version  : $Revision: 1.5 $
+#   Author   : $Author: fgerlits $
+#   Version  : $Revision: 1.6 $
 #   Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/schedulerClient/etc/Makefile.in,v $
 #
 #   @configure_input@
@@ -79,6 +79,11 @@ VPATH    = ${SRC_DIR}
 LIBXMLPP_CFLAGS=@LIBXMLPP_CFLAGS@
 LIBXMLPP_LIBS=@LIBXMLPP_LIBS@
 
+# TODO: move ICU flag determination to configure script
+ICU_LIBS=`${USR_DIR}/bin/icu-config --ldflags --ldflags-toolutil --ldflags-icuio`
+
+TAGLIB_LIBS     =`${USR_DIR}/bin/taglib-config --libs`
+
 TEST_RESULTS = ${DOC_DIR}/testResults.xml
 # the text result XSLT has to be relative to the test result file, e.g. TMP_DIR
 TEST_XSLT    = ../etc/testResultToHtml.xsl
@@ -106,6 +111,8 @@ CXXFLAGS = @CXXFLAGS@ @DEFS@ @COVERAGE_CXXFLAGS@ -pthread \
                              -I${INCLUDE_DIR} -I${TMP_DIR}
 LDFLAGS  = @LDFLAGS@ -pthread \
                      ${LIBXMLPP_LIBS} \
+                     ${ICU_LIBS} \
+                     ${TAGLIB_LIBS} \
                      -L${USR_LIB_DIR} \
                      -L${CORE_LIB_DIR} \
                      -L${AUTHENTICATION_LIB_DIR} \
diff --git a/livesupport/modules/schedulerClient/include/LiveSupport/SchedulerClient/SchedulerClientInterface.h b/livesupport/modules/schedulerClient/include/LiveSupport/SchedulerClient/SchedulerClientInterface.h
index 854b939c9..4990ea5ad 100644
--- a/livesupport/modules/schedulerClient/include/LiveSupport/SchedulerClient/SchedulerClientInterface.h
+++ b/livesupport/modules/schedulerClient/include/LiveSupport/SchedulerClient/SchedulerClientInterface.h
@@ -21,8 +21,8 @@
     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  
  
-    Author   : $Author: maroy $
-    Version  : $Revision: 1.4 $
+    Author   : $Author: fgerlits $
+    Version  : $Revision: 1.5 $
     Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/schedulerClient/include/LiveSupport/SchedulerClient/SchedulerClientInterface.h,v $
 
 ------------------------------------------------------------------------------*/
@@ -41,6 +41,7 @@
 #endif
 
 #include <stdexcept>
+#include <vector>
 #include "boost/date_time/posix_time/posix_time.hpp"
 
 #include "LiveSupport/Core/Ptr.h"
@@ -48,10 +49,13 @@
 #include "LiveSupport/Core/SessionId.h"
 #include "LiveSupport/Core/ScheduleEntry.h"
 #include "LiveSupport/Core/XmlRpcException.h"
+#include "LiveSupport/Core/Playlist.h"
+#include "LiveSupport/Core/AudioClip.h"
 
 namespace LiveSupport {
 namespace SchedulerClient {
 
+using namespace boost::posix_time;
 using namespace LiveSupport::Core;
 
 
@@ -66,8 +70,8 @@ using namespace LiveSupport::Core;
 /**
  *  An interface to access the scheduler daemon as a client.
  *
- *  @author  $Author: maroy $
- *  @version $Revision: 1.4 $
+ *  @author  $Author: fgerlits $
+ *  @version $Revision: 1.5 $
  */
 class SchedulerClientInterface
 {
@@ -89,7 +93,7 @@ class SchedulerClientInterface
          *  @return the current time at the scheduler server.
          *  @exception XmlRpcException in case of XML-RPC errors.
          */
-        virtual Ptr<const boost::posix_time::ptime>::Ref
+        virtual Ptr<const ptime>::Ref
         getSchedulerTime(void)                  throw (XmlRpcException)
                                                                         = 0;
 
@@ -104,9 +108,9 @@ class SchedulerClientInterface
          *  @exception XmlRpcException in case of XML-RPC errors.
          */
         virtual Ptr<UniqueId>::Ref
-        uploadPlaylist(Ptr<SessionId>::Ref                  sessionId,
-                       Ptr<UniqueId>::Ref                   playlistId,
-                       Ptr<boost::posix_time::ptime>::Ref   playtime)
+        uploadPlaylist(Ptr<SessionId>::Ref  sessionId,
+                       Ptr<UniqueId>::Ref   playlistId,
+                       Ptr<ptime>::Ref      playtime)
                                                     throw (XmlRpcException)
                                                                         = 0;
 
@@ -120,9 +124,9 @@ class SchedulerClientInterface
          *  @exception XmlRpcException in case of XML-RPC errors.
          */
         virtual Ptr<std::vector<Ptr<ScheduleEntry>::Ref> >::Ref
-        displaySchedule(Ptr<SessionId>::Ref                 sessionId,
-                        Ptr<boost::posix_time::ptime>::Ref  from,
-                        Ptr<boost::posix_time::ptime>::Ref  to)
+        displaySchedule(Ptr<SessionId>::Ref sessionId,
+                        Ptr<ptime>::Ref     from,
+                        Ptr<ptime>::Ref     to)
                                                     throw (XmlRpcException)
                                                                         = 0;
 
@@ -139,6 +143,104 @@ class SchedulerClientInterface
                                                     throw (XmlRpcException)
                                                                         = 0;
 
+        /**
+         *  Add an audio clip to a playlist.
+         *
+         *  @param sessionId a valid, authenticated session id.
+         *  @param playlistId the id of the playlist.
+         *  @param audioClipId the id of the audio clip.
+         *  @param relativeOffset the number of seconds between the start
+         *                of the playlist and the start of the audio clip.
+         *  @return the unique ID of the newly created playlist element.
+         *  @exception XmlRpcException in case of XML-RPC errors.
+         */
+        virtual Ptr<UniqueId>::Ref
+        addAudioClipToPlaylist(Ptr<SessionId>::Ref      sessionId,
+                               Ptr<UniqueId>::Ref       playlistId,
+                               Ptr<UniqueId>::Ref       audioClipId,
+                               Ptr<time_duration>::Ref  relativeOffset)
+                                                    throw (XmlRpcException)
+                                                                        = 0;
+
+        /**
+         *  Create a new playlist.
+         *
+         *  @param sessionId a valid, authenticated session id.
+         *  @return the newly created playlist.
+         *  @exception XmlRpcException in case of XML-RPC errors.
+         */
+        virtual Ptr<Playlist>::Ref
+        createPlaylist(Ptr<SessionId>::Ref      sessionId)
+                                                    throw (XmlRpcException)
+                                                                        = 0;
+
+        /**
+         *  Delete a playlist.
+         *
+         *  @param sessionId a valid, authenticated session id.
+         *  @param playlistId the id of the playlist.
+         *  @exception XmlRpcException in case of XML-RPC errors.
+         */
+        virtual void
+        deletePlaylist(Ptr<SessionId>::Ref      sessionId,
+                       Ptr<UniqueId>::Ref       playlistId)
+                                                    throw (XmlRpcException)
+                                                                        = 0;
+
+        /**
+         *  Return an audio clip.
+         *
+         *  @param sessionId a valid, authenticated session id.
+         *  @param audioClipId the id of the audio clip.
+         *  @return the audio clip.
+         *  @exception XmlRpcException in case of XML-RPC errors.
+         */
+        virtual Ptr<AudioClip>::Ref
+        displayAudioClip(Ptr<SessionId>::Ref      sessionId,
+                         Ptr<UniqueId>::Ref       audioClipId)
+                                                    throw (XmlRpcException)
+                                                                        = 0;
+
+        /**
+         *  Return a list of audio clips.  This method returns the audio
+         *  clips found by the latest search() on the storage client.
+         *
+         *  @param sessionId a valid, authenticated session id.
+         *  @return a std::vector of audio clips.
+         *  @exception XmlRpcException in case of XML-RPC errors.
+         */
+        virtual Ptr<std::vector<Ptr<AudioClip>::Ref> >::Ref
+        displayAudioClips(Ptr<SessionId>::Ref      sessionId)
+                                                    throw (XmlRpcException)
+                                                                        = 0;
+
+        /**
+         *  Return a playlist.
+         *
+         *  @param sessionId a valid, authenticated session id.
+         *  @param playlistId the id of the playlist.
+         *  @return the playlist.
+         *  @exception XmlRpcException in case of XML-RPC errors.
+         */
+        virtual Ptr<Playlist>::Ref
+        displayPlaylist(Ptr<SessionId>::Ref      sessionId,
+                        Ptr<UniqueId>::Ref       playlistId)
+                                                    throw (XmlRpcException)
+                                                                        = 0;
+
+        /**
+         *  Return a list of playlists.  This method returns the playlists
+         *  found by the latest search() on the storage client.
+         *
+         *  @param sessionId a valid, authenticated session id.
+         *  @return a std::vector of playlists.
+         *  @exception XmlRpcException in case of XML-RPC errors.
+         */
+        virtual Ptr<std::vector<Ptr<Playlist>::Ref> >::Ref
+        displayPlaylists(Ptr<SessionId>::Ref      sessionId)
+                                                    throw (XmlRpcException)
+                                                                        = 0;
+
 };
 
 
diff --git a/livesupport/modules/schedulerClient/src/SchedulerDaemonXmlRpcClient.cxx b/livesupport/modules/schedulerClient/src/SchedulerDaemonXmlRpcClient.cxx
index 3b46f8252..ddb569ba4 100644
--- a/livesupport/modules/schedulerClient/src/SchedulerDaemonXmlRpcClient.cxx
+++ b/livesupport/modules/schedulerClient/src/SchedulerDaemonXmlRpcClient.cxx
@@ -21,8 +21,8 @@
     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  
  
-    Author   : $Author: maroy $
-    Version  : $Revision: 1.5 $
+    Author   : $Author: fgerlits $
+    Version  : $Revision: 1.6 $
     Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/schedulerClient/src/SchedulerDaemonXmlRpcClient.cxx,v $
 
 ------------------------------------------------------------------------------*/
@@ -149,7 +149,7 @@ SchedulerDaemonXmlRpcClient :: getVersion(void)
 
     xmlRpcResult.clear();
     if (!xmlRpcClient.execute("getVersion", xmlRpcParams, xmlRpcResult)) {
-        throw XmlRpcCommunicationException(
+        throw Core::XmlRpcCommunicationException(
                                 "cannot execute XML-RPC method 'getVersion'");
     }
 
@@ -157,21 +157,21 @@ SchedulerDaemonXmlRpcClient :: getVersion(void)
         std::stringstream eMsg;
         eMsg << "XML-RPC method 'getVersion' returned error message:\n"
              << xmlRpcResult;
-        throw XmlRpcMethodFaultException(eMsg.str());
+        throw Core::XmlRpcMethodFaultException(eMsg.str());
     }
 
+    xmlRpcClient.close();
+
     if (!xmlRpcResult.hasMember("version")
       || xmlRpcResult["version"].getType() != XmlRpcValue::TypeString) {
         std::stringstream eMsg;
         eMsg << "XML-RPC method 'getVersion' returned unexpected value:\n"
              << xmlRpcResult;
-        throw XmlRpcMethodResponseException(eMsg.str());
+        throw Core::XmlRpcMethodResponseException(eMsg.str());
     }
 
     result.reset(new std::string(xmlRpcResult["version"]));
 
-    xmlRpcClient.close();
-
     return result;
 }
 
@@ -194,7 +194,7 @@ SchedulerDaemonXmlRpcClient :: getSchedulerTime(void)
 
     xmlRpcResult.clear();
     if (!xmlRpcClient.execute("getSchedulerTime", xmlRpcParams, xmlRpcResult)) {
-        throw XmlRpcCommunicationException(
+        throw Core::XmlRpcCommunicationException(
                             "cannot execute XML-RPC method 'getSchedulerTime'");
     }
 
@@ -202,15 +202,17 @@ SchedulerDaemonXmlRpcClient :: getSchedulerTime(void)
         std::stringstream eMsg;
         eMsg << "XML-RPC method 'getSchedulerTime' returned error message:\n"
              << xmlRpcResult;
-        throw XmlRpcMethodFaultException(eMsg.str());
+        throw Core::XmlRpcMethodFaultException(eMsg.str());
     }
 
+    xmlRpcClient.close();
+
     if (!xmlRpcResult.hasMember("schedulerTime")
      || xmlRpcResult["schedulerTime"].getType() != XmlRpcValue::TypeDateTime) {
         std::stringstream eMsg;
         eMsg << "XML-RPC method 'getSchedulerTime' returned unexpected value:\n"
              << xmlRpcResult;
-        throw XmlRpcMethodResponseException(eMsg.str());
+        throw Core::XmlRpcMethodResponseException(eMsg.str());
     }
 
     struct tm   time = xmlRpcResult["schedulerTime"];
@@ -218,11 +220,9 @@ SchedulerDaemonXmlRpcClient :: getSchedulerTime(void)
     try {
         result = TimeConversion::tmToPtime(&time);
     } catch (std::out_of_range &e) {
-        throw XmlRpcException("time conversion error", e);
+        throw Core::XmlRpcException("time conversion error", e);
     }
 
-    xmlRpcClient.close();
-
     return result;
 }
 
@@ -254,7 +254,7 @@ SchedulerDaemonXmlRpcClient :: uploadPlaylist(
 
     xmlRpcResult.clear();
     if (!xmlRpcClient.execute("uploadPlaylist", xmlRpcParams, xmlRpcResult)) {
-        throw XmlRpcCommunicationException(
+        throw Core::XmlRpcCommunicationException(
                             "cannot execute XML-RPC method 'uploadPlaylist'");
     }
 
@@ -262,17 +262,17 @@ SchedulerDaemonXmlRpcClient :: uploadPlaylist(
         std::stringstream eMsg;
         eMsg << "XML-RPC method 'uploadPlaylist' returned error message:\n"
              << xmlRpcResult;
-        throw XmlRpcMethodFaultException(eMsg.str());
+        throw Core::XmlRpcMethodFaultException(eMsg.str());
     }
 
+    xmlRpcClient.close();
+
     try {
         scheduleEntryId = XmlRpcTools::extractScheduleEntryId(xmlRpcResult);
     } catch (std::invalid_argument &e) {
-        throw XmlRpcInvalidArgumentException(e);
+        throw Core::XmlRpcInvalidArgumentException(e);
     }
 
-    xmlRpcClient.close();
-
     return scheduleEntryId;
 }
 
@@ -304,7 +304,7 @@ SchedulerDaemonXmlRpcClient :: displaySchedule(
 
     xmlRpcResult.clear();
     if (!xmlRpcClient.execute("displaySchedule", xmlRpcParams, xmlRpcResult)) {
-        throw XmlRpcCommunicationException(
+        throw Core::XmlRpcCommunicationException(
                             "cannot execute XML-RPC method 'displaySchedule'");
     }
 
@@ -312,17 +312,17 @@ SchedulerDaemonXmlRpcClient :: displaySchedule(
         std::stringstream eMsg;
         eMsg << "XML-RPC method 'displaySchedule' returned error message:\n"
              << xmlRpcResult;
-        throw XmlRpcMethodFaultException(eMsg.str());
+        throw Core::XmlRpcMethodFaultException(eMsg.str());
     }
 
+    xmlRpcClient.close();
+
     try {
         entries = XmlRpcTools::extractScheduleEntries(xmlRpcResult);
     } catch (std::invalid_argument &e) {
-        throw XmlRpcInvalidArgumentException(e);
+        throw Core::XmlRpcInvalidArgumentException(e);
     }
 
-    xmlRpcClient.close();
-
     return entries;
 }
 
@@ -352,7 +352,7 @@ SchedulerDaemonXmlRpcClient :: removeFromSchedule(
     if (!xmlRpcClient.execute("removeFromSchedule",
                               xmlRpcParams,
                               xmlRpcResult)) {
-        throw XmlRpcCommunicationException(
+        throw Core::XmlRpcCommunicationException(
                         "cannot execute XML-RPC method 'removeFromSchedule'");
     }
 
@@ -360,7 +360,340 @@ SchedulerDaemonXmlRpcClient :: removeFromSchedule(
         std::stringstream eMsg;
         eMsg << "XML-RPC method 'removeFromSchedule' returned error message:\n"
              << xmlRpcResult;
-        throw XmlRpcMethodFaultException(eMsg.str());
+        throw Core::XmlRpcMethodFaultException(eMsg.str());
+    }
+
+    xmlRpcClient.close();
+}
+
+
+/*------------------------------------------------------------------------------
+ *  Add an audio clip to a playlist.
+ *----------------------------------------------------------------------------*/
+Ptr<UniqueId>::Ref
+SchedulerDaemonXmlRpcClient :: addAudioClipToPlaylist(
+                                Ptr<SessionId>::Ref     sessionId,
+                                Ptr<UniqueId>::Ref      playlistId,
+                                Ptr<UniqueId>::Ref      audioClipId,
+                                Ptr<time_duration>::Ref relativeOffset)
+                                                throw (Core::XmlRpcException)
+{
+    XmlRpcValue             xmlRpcParams;
+    XmlRpcValue             xmlRpcResult;
+    Ptr<const ptime>::Ref   result;
+
+    XmlRpcClient            xmlRpcClient(xmlRpcHost->c_str(),
+                                         xmlRpcPort,
+                                         xmlRpcUri->c_str(),
+                                         false);
+
+    XmlRpcTools::sessionIdToXmlRpcValue(sessionId, xmlRpcParams);
+    XmlRpcTools::playlistIdToXmlRpcValue(playlistId, xmlRpcParams);
+    XmlRpcTools::audioClipIdToXmlRpcValue(audioClipId, xmlRpcParams);
+
+    xmlRpcResult.clear();
+    if (!xmlRpcClient.execute("addAudioClipToPlaylist",
+                              xmlRpcParams,
+                              xmlRpcResult)) {
+        throw Core::XmlRpcCommunicationException(
+                    "cannot execute XML-RPC method 'addAudioClipToPlaylist'");
+    }
+
+    if (xmlRpcClient.isFault()) {
+        std::stringstream eMsg;
+        eMsg << "XML-RPC method 'addAudioClipToPlaylist' returned "
+                "error message:\n"
+             << xmlRpcResult;
+        throw Core::XmlRpcMethodFaultException(eMsg.str());
+    }
+
+    xmlRpcClient.close();
+
+    Ptr<UniqueId>::Ref      playlistElementId;
+    try {
+        playlistElementId = XmlRpcTools::extractPlaylistElementId(xmlRpcResult);
+    } catch (std::invalid_argument &e) {
+        throw Core::XmlRpcInvalidArgumentException(e);
+    }
+
+    return playlistElementId;
+}
+
+
+/*------------------------------------------------------------------------------
+ *  Create a new playlist.
+ *----------------------------------------------------------------------------*/
+Ptr<Playlist>::Ref
+SchedulerDaemonXmlRpcClient :: createPlaylist(
+                                Ptr<SessionId>::Ref  sessionId)
+                                                throw (Core::XmlRpcException)
+{
+    XmlRpcValue             xmlRpcParams;
+    XmlRpcValue             xmlRpcResult;
+    Ptr<const ptime>::Ref   result;
+
+    XmlRpcClient            xmlRpcClient(xmlRpcHost->c_str(),
+                                         xmlRpcPort,
+                                         xmlRpcUri->c_str(),
+                                         false);
+
+    XmlRpcTools::sessionIdToXmlRpcValue(sessionId, xmlRpcParams);
+
+    xmlRpcResult.clear();
+    if (!xmlRpcClient.execute("createPlaylist",
+                              xmlRpcParams,
+                              xmlRpcResult)) {
+        throw Core::XmlRpcCommunicationException(
+                    "cannot execute XML-RPC method 'createPlaylist'");
+    }
+
+    if (xmlRpcClient.isFault()) {
+        std::stringstream eMsg;
+        eMsg << "XML-RPC method 'createPlaylist' returned "
+                "error message:\n"
+             << xmlRpcResult;
+        throw Core::XmlRpcMethodFaultException(eMsg.str());
+    }
+
+    xmlRpcClient.close();
+
+    Ptr<Playlist>::Ref      playlist;
+    try {
+        playlist = XmlRpcTools::extractPlaylist(xmlRpcResult);
+    } catch (std::invalid_argument &e) {
+        throw Core::XmlRpcInvalidArgumentException(e);
+    }
+
+    return playlist;
+}
+
+
+/*------------------------------------------------------------------------------
+ *  Delete a playlist.
+ *----------------------------------------------------------------------------*/
+void
+SchedulerDaemonXmlRpcClient :: deletePlaylist(
+                                Ptr<SessionId>::Ref     sessionId,
+                                Ptr<UniqueId>::Ref      playlistId)
+                                                throw (Core::XmlRpcException)
+{
+    XmlRpcValue             xmlRpcParams;
+    XmlRpcValue             xmlRpcResult;
+    Ptr<const ptime>::Ref   result;
+
+    XmlRpcClient            xmlRpcClient(xmlRpcHost->c_str(),
+                                         xmlRpcPort,
+                                         xmlRpcUri->c_str(),
+                                         false);
+
+    XmlRpcTools::sessionIdToXmlRpcValue(sessionId, xmlRpcParams);
+    XmlRpcTools::playlistIdToXmlRpcValue(playlistId, xmlRpcParams);
+
+    xmlRpcResult.clear();
+    if (!xmlRpcClient.execute("deletePlaylist",
+                              xmlRpcParams,
+                              xmlRpcResult)) {
+        throw Core::XmlRpcCommunicationException(
+                    "cannot execute XML-RPC method 'deletePlaylist'");
+    }
+
+    if (xmlRpcClient.isFault()) {
+        std::stringstream eMsg;
+        eMsg << "XML-RPC method 'deletePlaylist' returned error message:\n"
+             << xmlRpcResult;
+        throw Core::XmlRpcMethodFaultException(eMsg.str());
     }
 }
 
+
+/*------------------------------------------------------------------------------
+ *  Return an audio clip.
+ *----------------------------------------------------------------------------*/
+Ptr<AudioClip>::Ref
+SchedulerDaemonXmlRpcClient :: displayAudioClip(
+                                Ptr<SessionId>::Ref     sessionId,
+                                Ptr<UniqueId>::Ref      audioClipId)
+                                                throw (Core::XmlRpcException)
+{
+    XmlRpcValue             xmlRpcParams;
+    XmlRpcValue             xmlRpcResult;
+    Ptr<const ptime>::Ref   result;
+
+    XmlRpcClient            xmlRpcClient(xmlRpcHost->c_str(),
+                                         xmlRpcPort,
+                                         xmlRpcUri->c_str(),
+                                         false);
+
+    XmlRpcTools::sessionIdToXmlRpcValue(sessionId, xmlRpcParams);
+    XmlRpcTools::audioClipIdToXmlRpcValue(audioClipId, xmlRpcParams);
+
+    xmlRpcResult.clear();
+    if (!xmlRpcClient.execute("displayAudioClip",
+                              xmlRpcParams,
+                              xmlRpcResult)) {
+        throw Core::XmlRpcCommunicationException(
+                    "cannot execute XML-RPC method 'displayAudioClip'");
+    }
+
+    if (xmlRpcClient.isFault()) {
+        std::stringstream eMsg;
+        eMsg << "XML-RPC method 'displayAudioClip' returned error message:\n"
+             << xmlRpcResult;
+        throw Core::XmlRpcMethodFaultException(eMsg.str());
+    }
+
+    xmlRpcClient.close();
+
+    Ptr<AudioClip>::Ref     audioClip;
+    try {
+        audioClip = XmlRpcTools::extractAudioClip(xmlRpcResult);
+    } catch (std::invalid_argument &e) {
+        throw Core::XmlRpcInvalidArgumentException(e);
+    }
+
+    return audioClip;
+}
+
+
+/*------------------------------------------------------------------------------
+ *  Return a list of audio clips.
+ *----------------------------------------------------------------------------*/
+Ptr<std::vector<Ptr<AudioClip>::Ref> >::Ref
+SchedulerDaemonXmlRpcClient :: displayAudioClips(
+                                Ptr<SessionId>::Ref     sessionId)
+                                                throw (Core::XmlRpcException)
+{
+    XmlRpcValue             xmlRpcParams;
+    XmlRpcValue             xmlRpcResult;
+    Ptr<const ptime>::Ref   result;
+
+    XmlRpcClient            xmlRpcClient(xmlRpcHost->c_str(),
+                                         xmlRpcPort,
+                                         xmlRpcUri->c_str(),
+                                         false);
+
+    XmlRpcTools::sessionIdToXmlRpcValue(sessionId, xmlRpcParams);
+
+    xmlRpcResult.clear();
+    if (!xmlRpcClient.execute("displayAudioClips",
+                              xmlRpcParams,
+                              xmlRpcResult)) {
+        throw Core::XmlRpcCommunicationException(
+                    "cannot execute XML-RPC method 'displayAudioClips'");
+    }
+
+    if (xmlRpcClient.isFault()) {
+        std::stringstream eMsg;
+        eMsg << "XML-RPC method 'displayAudioClips' returned error message:\n"
+             << xmlRpcResult;
+        throw Core::XmlRpcMethodFaultException(eMsg.str());
+    }
+
+    xmlRpcClient.close();
+
+    Ptr<std::vector<Ptr<AudioClip>::Ref> >::Ref     audioClipVector;
+    try {
+        audioClipVector = XmlRpcTools::extractAudioClipVector(xmlRpcResult);
+    } catch (std::invalid_argument &e) {
+        throw Core::XmlRpcInvalidArgumentException(e);
+    }
+
+    return audioClipVector;
+}
+
+
+/*------------------------------------------------------------------------------
+ *  Return a playlist.
+ *----------------------------------------------------------------------------*/
+Ptr<Playlist>::Ref
+SchedulerDaemonXmlRpcClient :: displayPlaylist(
+                                Ptr<SessionId>::Ref     sessionId,
+                                Ptr<UniqueId>::Ref      playlistId)
+                                                throw (Core::XmlRpcException)
+{
+    XmlRpcValue             xmlRpcParams;
+    XmlRpcValue             xmlRpcResult;
+    Ptr<const ptime>::Ref   result;
+
+    XmlRpcClient            xmlRpcClient(xmlRpcHost->c_str(),
+                                         xmlRpcPort,
+                                         xmlRpcUri->c_str(),
+                                         false);
+
+    XmlRpcTools::sessionIdToXmlRpcValue(sessionId, xmlRpcParams);
+    XmlRpcTools::playlistIdToXmlRpcValue(playlistId, xmlRpcParams);
+
+    xmlRpcResult.clear();
+    if (!xmlRpcClient.execute("displayPlaylist",
+                              xmlRpcParams,
+                              xmlRpcResult)) {
+        throw Core::XmlRpcCommunicationException(
+                    "cannot execute XML-RPC method 'displayPlaylist'");
+    }
+
+    if (xmlRpcClient.isFault()) {
+        std::stringstream eMsg;
+        eMsg << "XML-RPC method 'displayPlaylist' returned error message:\n"
+             << xmlRpcResult;
+        throw Core::XmlRpcMethodFaultException(eMsg.str());
+    }
+
+    xmlRpcClient.close();
+
+    Ptr<Playlist>::Ref     playlist;
+    try {
+        playlist = XmlRpcTools::extractPlaylist(xmlRpcResult);
+    } catch (std::invalid_argument &e) {
+        throw Core::XmlRpcInvalidArgumentException(e);
+    }
+
+    return playlist;
+}
+
+
+/*------------------------------------------------------------------------------
+ *  Return a list of playlists.
+ *----------------------------------------------------------------------------*/
+Ptr<std::vector<Ptr<Playlist>::Ref> >::Ref
+SchedulerDaemonXmlRpcClient :: displayPlaylists(
+                                Ptr<SessionId>::Ref     sessionId)
+                                                throw (Core::XmlRpcException)
+{
+    XmlRpcValue             xmlRpcParams;
+    XmlRpcValue             xmlRpcResult;
+    Ptr<const ptime>::Ref   result;
+
+    XmlRpcClient            xmlRpcClient(xmlRpcHost->c_str(),
+                                         xmlRpcPort,
+                                         xmlRpcUri->c_str(),
+                                         false);
+
+    XmlRpcTools::sessionIdToXmlRpcValue(sessionId, xmlRpcParams);
+
+    xmlRpcResult.clear();
+    if (!xmlRpcClient.execute("displayPlaylists",
+                              xmlRpcParams,
+                              xmlRpcResult)) {
+        throw Core::XmlRpcCommunicationException(
+                    "cannot execute XML-RPC method 'displayPlaylists'");
+    }
+
+    if (xmlRpcClient.isFault()) {
+        std::stringstream eMsg;
+        eMsg << "XML-RPC method 'displayPlaylists' returned error message:\n"
+             << xmlRpcResult;
+        throw Core::XmlRpcMethodFaultException(eMsg.str());
+    }
+
+    xmlRpcClient.close();
+
+    Ptr<std::vector<Ptr<Playlist>::Ref> >::Ref     playlistVector;
+    try {
+        playlistVector = XmlRpcTools::extractPlaylistVector(xmlRpcResult);
+    } catch (std::invalid_argument &e) {
+        throw Core::XmlRpcInvalidArgumentException(e);
+    }
+
+    return playlistVector;
+}
+
diff --git a/livesupport/modules/schedulerClient/src/SchedulerDaemonXmlRpcClient.h b/livesupport/modules/schedulerClient/src/SchedulerDaemonXmlRpcClient.h
index ad81362bc..9c09c31c7 100644
--- a/livesupport/modules/schedulerClient/src/SchedulerDaemonXmlRpcClient.h
+++ b/livesupport/modules/schedulerClient/src/SchedulerDaemonXmlRpcClient.h
@@ -21,8 +21,8 @@
     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  
  
-    Author   : $Author: maroy $
-    Version  : $Revision: 1.4 $
+    Author   : $Author: fgerlits $
+    Version  : $Revision: 1.5 $
     Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/schedulerClient/src/SchedulerDaemonXmlRpcClient.h,v $
 
 ------------------------------------------------------------------------------*/
@@ -48,6 +48,9 @@
 
 #include "LiveSupport/Core/Ptr.h"
 #include "LiveSupport/Core/Configurable.h"
+#include "LiveSupport/Core/Playlist.h"
+#include "LiveSupport/Core/AudioClip.h"
+
 #include "LiveSupport/SchedulerClient/SchedulerClientInterface.h"
 
 
@@ -76,8 +79,8 @@ using namespace LiveSupport::Core;
  *
  *  <pre><code>
  *  &lt;schedulerDaemonXmlRpcClient xmlRpcHost = "localhost"
- *                                  xmlRpcPort = "3344"
- *                                  xmlRpcUri  = "/RC2"
+ *                               xmlRpcPort = "3344"
+ *                               xmlRpcUri  = "/RC2"
  *  /&gt;
  *  </code></pre>
  *
@@ -90,8 +93,8 @@ using namespace LiveSupport::Core;
  *  <!ATTLIST schedulerDaemonXmlRpcClient xmlRpcUri     CDATA       #REQUIRED >
  *  </code></pre>
  *
- *  @author  $Author: maroy $
- *  @version $Revision: 1.4 $
+ *  @author  $Author: fgerlits $
+ *  @version $Revision: 1.5 $
  */
 class SchedulerDaemonXmlRpcClient :
                     virtual public Configurable,
@@ -217,6 +220,97 @@ class SchedulerDaemonXmlRpcClient :
                            Ptr<UniqueId>::Ref   scheduleEntryId)
                                                     throw (XmlRpcException);
 
+        /**
+         *  Add an audio clip to a playlist.
+         *
+         *  @param sessionId a valid, authenticated session id.
+         *  @param playlistId the id of the playlist.
+         *  @param audioClipId the id of the audio clip.
+         *  @param relativeOffset the number of seconds between the start
+         *                of the playlist and the start of the audio clip.
+         *  @return the unique ID of the newly created playlist element.
+         *  @exception XmlRpcException in case of XML-RPC errors.
+         */
+        virtual Ptr<UniqueId>::Ref
+        addAudioClipToPlaylist(Ptr<SessionId>::Ref      sessionId,
+                               Ptr<UniqueId>::Ref       playlistId,
+                               Ptr<UniqueId>::Ref       audioClipId,
+                               Ptr<time_duration>::Ref  relativeOffset)
+                                                    throw (XmlRpcException);
+
+        /**
+         *  Create a new playlist.
+         *
+         *  @param sessionId a valid, authenticated session id.
+         *  @return the newly created playlist.
+         *  @exception XmlRpcException in case of XML-RPC errors.
+         */
+        virtual Ptr<Playlist>::Ref
+        createPlaylist(Ptr<SessionId>::Ref      sessionId)
+                                                    throw (XmlRpcException);
+
+        /**
+         *  Delete a playlist.
+         *
+         *  @param sessionId a valid, authenticated session id.
+         *  @param playlistId the id of the playlist.
+         *  @exception XmlRpcException in case of XML-RPC errors.
+         */
+        virtual void
+        deletePlaylist(Ptr<SessionId>::Ref      sessionId,
+                       Ptr<UniqueId>::Ref       playlistId)
+                                                    throw (XmlRpcException);
+
+        /**
+         *  Return an audio clip.
+         *
+         *  @param sessionId a valid, authenticated session id.
+         *  @param audioClipId the id of the audio clip.
+         *  @return the audio clip.
+         *  @exception XmlRpcException in case of XML-RPC errors.
+         */
+        virtual Ptr<AudioClip>::Ref
+        displayAudioClip(Ptr<SessionId>::Ref      sessionId,
+                         Ptr<UniqueId>::Ref       audioClipId)
+                                                    throw (XmlRpcException);
+
+        /**
+         *  Return a list of audio clips.  This method returns the audio
+         *  clips found by the latest search() on the storage client.
+         *
+         *  @param sessionId a valid, authenticated session id.
+         *  @return a std::vector of audio clips.
+         *  @exception XmlRpcException in case of XML-RPC errors.
+         */
+        virtual Ptr<std::vector<Ptr<AudioClip>::Ref> >::Ref
+        displayAudioClips(Ptr<SessionId>::Ref      sessionId)
+                                                    throw (XmlRpcException);
+
+        /**
+         *  Return a playlist.
+         *
+         *  @param sessionId a valid, authenticated session id.
+         *  @param playlistId the id of the playlist.
+         *  @return the playlist.
+         *  @exception XmlRpcException in case of XML-RPC errors.
+         */
+        virtual Ptr<Playlist>::Ref
+        displayPlaylist(Ptr<SessionId>::Ref      sessionId,
+                        Ptr<UniqueId>::Ref       playlistId)
+                                                    throw (XmlRpcException);
+
+        /**
+         *  Return a list of playlists.  This method returns the playlists
+         *  found by the latest search() on the storage client.
+         *
+         *  @param sessionId a valid, authenticated session id.
+         *  @return a std::vector of playlists.
+         *  @exception XmlRpcException in case of XML-RPC errors.
+         */
+        virtual Ptr<std::vector<Ptr<Playlist>::Ref> >::Ref
+        displayPlaylists(Ptr<SessionId>::Ref      sessionId)
+                                                    throw (XmlRpcException);
+
 };
 
 
diff --git a/livesupport/modules/schedulerClient/src/SchedulerDaemonXmlRpcClientTest.cxx b/livesupport/modules/schedulerClient/src/SchedulerDaemonXmlRpcClientTest.cxx
index 68268567d..ec268efc2 100644
--- a/livesupport/modules/schedulerClient/src/SchedulerDaemonXmlRpcClientTest.cxx
+++ b/livesupport/modules/schedulerClient/src/SchedulerDaemonXmlRpcClientTest.cxx
@@ -21,8 +21,8 @@
     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  
  
-    Author   : $Author: maroy $
-    Version  : $Revision: 1.4 $
+    Author   : $Author: fgerlits $
+    Version  : $Revision: 1.5 $
     Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/schedulerClient/src/SchedulerDaemonXmlRpcClientTest.cxx,v $
 
 ------------------------------------------------------------------------------*/
@@ -43,6 +43,8 @@
 #include <string>
 #include <fstream>
 #include <iostream>
+#include <XmlRpcClient.h>
+#include <XmlRpcValue.h>
 
 #include "LiveSupport/Core/TimeConversion.h"
 #include "LiveSupport/Core/XmlRpcMethodFaultException.h"
@@ -116,23 +118,23 @@ SchedulerDaemonXmlRpcClientTest :: setUp(void)                         throw ()
         CPPUNIT_FAIL("error parsing configuration file");
     }
 
-    try {
-        Ptr<AuthenticationClientFactory>::Ref acf;
-        acf = AuthenticationClientFactory::getInstance();
-        configure(acf, authenticationClientConfigFileName);
-        authentication = acf->getAuthenticationClient();
-    } catch (std::invalid_argument &e) {
-        std::cerr << e.what() << std::endl;
-        CPPUNIT_FAIL("semantic error in authentication configuration file");
-    } catch (xmlpp::exception &e) {
-        std::cerr << e.what() << std::endl;
-        CPPUNIT_FAIL("error parsing authentication configuration file");
-    }
+    XmlRpc::XmlRpcValue     parameters;
+    XmlRpc::XmlRpcValue     result;
 
-    if (!(sessionId = authentication->login("root", "q"))) {
-        CPPUNIT_FAIL("could not log in to authentication server");
-    }
+    XmlRpc::XmlRpcClient    xmlRpcClient("localhost", 3344, "/RPC2", false);
 
+    CPPUNIT_ASSERT(xmlRpcClient.execute("resetStorage", parameters, result));
+    CPPUNIT_ASSERT(!xmlRpcClient.isFault());
+
+    parameters["login"]     = "root";
+    parameters["password"]  = "q";
+    CPPUNIT_ASSERT(xmlRpcClient.execute("login", parameters, result));
+    CPPUNIT_ASSERT(!xmlRpcClient.isFault());
+    CPPUNIT_ASSERT(result.hasMember("sessionId"));
+
+    xmlRpcClient.close();
+
+    sessionId.reset(new SessionId(std::string(result["sessionId"])));
 }
 
 
@@ -142,11 +144,16 @@ SchedulerDaemonXmlRpcClientTest :: setUp(void)                         throw ()
 void
 SchedulerDaemonXmlRpcClientTest :: tearDown(void)                      throw ()
 {
-    schedulerClient.reset();
+    XmlRpc::XmlRpcValue     parameters;
+    XmlRpc::XmlRpcValue     result;
 
-    authentication->logout(sessionId);
-    sessionId.reset();
-    authentication.reset();
+    XmlRpc::XmlRpcClient    xmlRpcClient("localhost", 3344, "/RPC2", false);
+
+    parameters["sessionId"] = sessionId->getId();
+    CPPUNIT_ASSERT(xmlRpcClient.execute("logout", parameters, result));
+    CPPUNIT_ASSERT(!xmlRpcClient.isFault());
+
+    xmlRpcClient.close();
 }
 
 
@@ -161,7 +168,7 @@ SchedulerDaemonXmlRpcClientTest :: getVersionTest(void)
         Ptr<const std::string>::Ref     version = schedulerClient->getVersion();
 
         CPPUNIT_ASSERT(version.get());
-    } catch (XmlRpcException &e) {
+    } catch (Core::XmlRpcException &e) {
         CPPUNIT_FAIL(e.what());
     }
 }
@@ -182,7 +189,7 @@ SchedulerDaemonXmlRpcClientTest :: getSchedulerTimeTest(void)
         // assume that the scheduler and the client is in the same year
         // this can break at new year's eve - so don't run the test then :)
         CPPUNIT_ASSERT(time->date().year() == now->date().year());
-    } catch (XmlRpcException &e) {
+    } catch (Core::XmlRpcException &e) {
         CPPUNIT_FAIL(e.what());
     }
 }
@@ -206,12 +213,66 @@ SchedulerDaemonXmlRpcClientTest :: displayScheduleEmptyTest(void)
 
         entries = schedulerClient->displaySchedule(sessionId, from, to);
         CPPUNIT_ASSERT(entries->empty());
-    } catch (XmlRpcException &e) {
+    } catch (Core::XmlRpcException &e) {
         CPPUNIT_FAIL(e.what());
     }
 }
 
 
+/*------------------------------------------------------------------------------
+ *  Test some simple playlist operations.
+ *----------------------------------------------------------------------------*/
+void
+SchedulerDaemonXmlRpcClientTest :: displayPlaylistTest(void)
+                                                throw (CPPUNIT_NS::Exception)
+{
+    Ptr<Playlist>::Ref      playlist;
+    Ptr<UniqueId>::Ref      playlistId;
+
+    // the test assumes that 
+    //  * there is a playlist with the id of 1
+    //  * there is no playlist with the id of 9999
+    // in the storage accessed by the scheduler daemon
+
+    playlistId.reset(new UniqueId(1));
+    CPPUNIT_ASSERT_NO_THROW(
+        playlist = schedulerClient->displayPlaylist(sessionId, playlistId)
+    );
+    CPPUNIT_ASSERT(playlist->getId()->getId() == 1);
+    
+    playlistId.reset(new UniqueId(9999));
+    CPPUNIT_ASSERT_THROW(
+        playlist = schedulerClient->displayPlaylist(sessionId, playlistId),
+        Core::XmlRpcMethodFaultException
+    );
+    
+    CPPUNIT_ASSERT_NO_THROW(
+        playlist = schedulerClient->createPlaylist(sessionId)
+    );
+    CPPUNIT_ASSERT(playlistId->getId() >= 0);
+
+    playlistId = playlist->getId();
+    CPPUNIT_ASSERT_NO_THROW(
+        playlist = schedulerClient->displayPlaylist(sessionId, playlistId)
+    );
+    CPPUNIT_ASSERT(*playlist->getId() == *playlistId);
+    CPPUNIT_ASSERT(playlist->getPlaylength()->total_seconds() == 0);
+
+// This doesn't work yet: createPlaylist() opens the playlist for editing,
+// and so far we have no way of saving it.
+/*
+    CPPUNIT_ASSERT_NO_THROW(
+        schedulerClient->deletePlaylist(sessionId, playlistId)
+    );
+
+    CPPUNIT_ASSERT_THROW(
+        playlist = schedulerClient->displayPlaylist(sessionId, playlistId),
+        Core::XmlRpcMethodFaultException
+    );
+*/
+}
+
+
 /*------------------------------------------------------------------------------
  *  Test playlist management functions.
  *----------------------------------------------------------------------------*/
@@ -261,7 +322,7 @@ SchedulerDaemonXmlRpcClientTest :: playlistMgmtTest(void)
         schedulerClient->removeFromSchedule(sessionId, entryId);
         entries = schedulerClient->displaySchedule(sessionId, from, to);
         CPPUNIT_ASSERT(entries->empty());
-    } catch (XmlRpcException &e) {
+    } catch (Core::XmlRpcException &e) {
         CPPUNIT_FAIL(e.what());
     }
 }
@@ -298,7 +359,7 @@ SchedulerDaemonXmlRpcClientTest :: xmlRpcErrorTest(void)
         entryId = schedulerClient->uploadPlaylist(sessionId,
                                                   playlistId,
                                                   playtime);
-    } catch (XmlRpcException &e) {
+    } catch (Core::XmlRpcException &e) {
         CPPUNIT_FAIL(e.what());
     }
 
@@ -307,9 +368,9 @@ SchedulerDaemonXmlRpcClientTest :: xmlRpcErrorTest(void)
         // try to upload the same entry again, for the same time
         // this should result in an error
         schedulerClient->uploadPlaylist(sessionId, playlistId, playtime);
-    } catch (LiveSupport::Core::XmlRpcMethodFaultException &e) {
+    } catch (Core::XmlRpcMethodFaultException &e) {
         gotException = true;
-    } catch (XmlRpcException &e) {
+    } catch (Core::XmlRpcException &e) {
         CPPUNIT_FAIL(e.what());
     }
     CPPUNIT_ASSERT(gotException);
@@ -322,7 +383,7 @@ SchedulerDaemonXmlRpcClientTest :: xmlRpcErrorTest(void)
         schedulerClient->removeFromSchedule(sessionId, entryId);
         entries = schedulerClient->displaySchedule(sessionId, from, to);
         CPPUNIT_ASSERT(entries->empty());
-    } catch (XmlRpcException &e) {
+    } catch (Core::XmlRpcException &e) {
         CPPUNIT_FAIL(e.what());
     }
 
@@ -331,9 +392,9 @@ SchedulerDaemonXmlRpcClientTest :: xmlRpcErrorTest(void)
         // and now, try to remove it again, which should result in an
         // exception
         schedulerClient->removeFromSchedule(sessionId, entryId);
-    } catch (LiveSupport::Core::XmlRpcMethodFaultException &e) {
+    } catch (Core::XmlRpcMethodFaultException &e) {
         gotException = true;
-    } catch (XmlRpcException &e) {
+    } catch (Core::XmlRpcException &e) {
         CPPUNIT_FAIL(e.what());
     }
     CPPUNIT_ASSERT(gotException);
diff --git a/livesupport/modules/schedulerClient/src/SchedulerDaemonXmlRpcClientTest.h b/livesupport/modules/schedulerClient/src/SchedulerDaemonXmlRpcClientTest.h
index 80722a021..c37048564 100644
--- a/livesupport/modules/schedulerClient/src/SchedulerDaemonXmlRpcClientTest.h
+++ b/livesupport/modules/schedulerClient/src/SchedulerDaemonXmlRpcClientTest.h
@@ -21,8 +21,8 @@
     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  
  
-    Author   : $Author: maroy $
-    Version  : $Revision: 1.4 $
+    Author   : $Author: fgerlits $
+    Version  : $Revision: 1.5 $
     Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/schedulerClient/src/SchedulerDaemonXmlRpcClientTest.h,v $
 
 ------------------------------------------------------------------------------*/
@@ -62,8 +62,8 @@ using namespace LiveSupport::Authentication;
 /**
  *  Unit test for the SchedulerDaemonXmlRpcClient class.
  *
- *  @author  $Author: maroy $
- *  @version $Revision: 1.4 $
+ *  @author  $Author: fgerlits $
+ *  @version $Revision: 1.5 $
  *  @see SchedulerDaemonXmlRpcClient
  */
 class SchedulerDaemonXmlRpcClientTest : public CPPUNIT_NS::TestFixture
@@ -72,6 +72,7 @@ class SchedulerDaemonXmlRpcClientTest : public CPPUNIT_NS::TestFixture
     CPPUNIT_TEST(getVersionTest);
     CPPUNIT_TEST(getSchedulerTimeTest);
     CPPUNIT_TEST(displayScheduleEmptyTest);
+    CPPUNIT_TEST(displayPlaylistTest);
     CPPUNIT_TEST(playlistMgmtTest);
     CPPUNIT_TEST(xmlRpcErrorTest);
     CPPUNIT_TEST_SUITE_END();
@@ -82,11 +83,6 @@ class SchedulerDaemonXmlRpcClientTest : public CPPUNIT_NS::TestFixture
          */
         Ptr<SchedulerDaemonXmlRpcClient>::Ref   schedulerClient;
 
-        /**
-         *  An authentication client.
-         */
-        Ptr<AuthenticationClientInterface>::Ref authentication;
-
         /**
          *  A session ID from the authentication client login() method.
          */
@@ -134,6 +130,14 @@ class SchedulerDaemonXmlRpcClientTest : public CPPUNIT_NS::TestFixture
         void
         displayScheduleEmptyTest(void)          throw (CPPUNIT_NS::Exception);
 
+        /**
+         *  Test some simple playlist operations.
+         *
+         *  @exception CPPUNIT_NS::Exception on test failures.
+         */
+        void
+        displayPlaylistTest(void)               throw (CPPUNIT_NS::Exception);
+
         /**
          *  Test playlist management.
          *
diff --git a/livesupport/products/scheduler/src/GetSchedulerTimeMethod.h b/livesupport/products/scheduler/src/GetSchedulerTimeMethod.h
index 39181f377..0c75d72e8 100644
--- a/livesupport/products/scheduler/src/GetSchedulerTimeMethod.h
+++ b/livesupport/products/scheduler/src/GetSchedulerTimeMethod.h
@@ -22,7 +22,7 @@
  
  
     Author   : $Author: fgerlits $
-    Version  : $Revision: 1.2 $
+    Version  : $Revision: 1.3 $
     Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/products/scheduler/src/GetSchedulerTimeMethod.h,v $
 
 ------------------------------------------------------------------------------*/
@@ -78,15 +78,15 @@ using namespace LiveSupport::Core;
  *  No input parameters are expected.
  *
  *  The XML-RPC function returns an XML-RPC structure containing a single
- *  date/time field:
+ *  ISO 8601 DateTime field:
  *  <ul>
- *      <li>schedulerTime - date/time - the local time on the scheduler</li>
+ *      <li>schedulerTime - datetime - the local time on the scheduler</li>
  *  </ul>
  *
  *  This method does not generate any fault responses.
  *
  *  @author  $Author: fgerlits $
- *  @version $Revision: 1.2 $
+ *  @version $Revision: 1.3 $
  */
 class GetSchedulerTimeMethod : public XmlRpc::XmlRpcServerMethod
 {
diff --git a/livesupport/products/scheduler/src/UploadPlaylistMethod.h b/livesupport/products/scheduler/src/UploadPlaylistMethod.h
index b04e3a439..ffd01ad9d 100644
--- a/livesupport/products/scheduler/src/UploadPlaylistMethod.h
+++ b/livesupport/products/scheduler/src/UploadPlaylistMethod.h
@@ -22,7 +22,7 @@
  
  
     Author   : $Author: fgerlits $
-    Version  : $Revision: 1.10 $
+    Version  : $Revision: 1.11 $
     Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/products/scheduler/src/UploadPlaylistMethod.h,v $
 
 ------------------------------------------------------------------------------*/
@@ -76,9 +76,9 @@ using namespace LiveSupport::Core;
  *  <ul>
  *      <li>sessionId  - string - the session ID obtained via the login()
  *                                method of the authentication client </li>
- *      <li>playlistId - int, the id of the playlist to upload</li>
- *      <li>playtime - the time when the playlist should be scheduled,
- *                     an ISO 8601 DateTime field</li>
+ *      <li>playlistId - string - the id of the playlist to upload</li>
+ *      <li>playtime - datetime - the time when the playlist should be 
+ *                                scheduled, an ISO 8601 DateTime field</li>
  *  </ul>
  *
  *  If the upload is successful, the method returns an XML-RPC structure with
@@ -102,7 +102,7 @@ using namespace LiveSupport::Core;
  *  </ul>
  *
  *  @author  $Author: fgerlits $
- *  @version $Revision: 1.10 $
+ *  @version $Revision: 1.11 $
  */
 class UploadPlaylistMethod : public XmlRpc::XmlRpcServerMethod
 {