From 692230835a22bb7e1050c953cba21fd42e9d2016 Mon Sep 17 00:00:00 2001 From: maroy Date: Mon, 8 Nov 2004 13:20:37 +0000 Subject: [PATCH] added initial version of the event scheduler and audio player integrated into the scheduler daemon --- .../products/scheduler/etc/Makefile.in | 53 ++++- .../products/scheduler/etc/configure.ac | 6 +- .../products/scheduler/etc/scheduler.xml | 11 +- .../products/scheduler/src/PlaylistEvent.cxx | 116 ++++++++++ .../products/scheduler/src/PlaylistEvent.h | 215 ++++++++++++++++++ .../scheduler/src/PlaylistEventContainer.cxx | 92 ++++++++ .../scheduler/src/PlaylistEventContainer.h | 139 +++++++++++ .../scheduler/src/PostgresqlSchedule.cxx | 58 ++++- .../scheduler/src/PostgresqlSchedule.h | 22 +- .../scheduler/src/PostgresqlScheduleTest.cxx | 54 ++++- .../scheduler/src/PostgresqlScheduleTest.h | 14 +- .../scheduler/src/ScheduleInterface.h | 17 +- .../scheduler/src/SchedulerDaemon.cxx | 75 +++++- .../products/scheduler/src/SchedulerDaemon.h | 48 +++- .../products/scheduler/src/XmlRpcDaemon.h | 8 +- livesupport/products/scheduler/src/main.cxx | 18 +- 16 files changed, 903 insertions(+), 43 deletions(-) create mode 100644 livesupport/products/scheduler/src/PlaylistEvent.cxx create mode 100644 livesupport/products/scheduler/src/PlaylistEvent.h create mode 100644 livesupport/products/scheduler/src/PlaylistEventContainer.cxx create mode 100644 livesupport/products/scheduler/src/PlaylistEventContainer.h diff --git a/livesupport/products/scheduler/etc/Makefile.in b/livesupport/products/scheduler/etc/Makefile.in index 8980fe893..029a5a004 100644 --- a/livesupport/products/scheduler/etc/Makefile.in +++ b/livesupport/products/scheduler/etc/Makefile.in @@ -20,8 +20,8 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # -# Author : $Author: fgerlits $ -# Version : $Revision: 1.20 $ +# Author : $Author: maroy $ +# Version : $Revision: 1.21 $ # Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/products/scheduler/etc/Makefile.in,v $ # # @configure_input@ @@ -53,6 +53,14 @@ USR_LIB_DIR = ${USR_DIR}/lib BOOST_INCLUDE_DIR = ${USR_INCLUDE_DIR}/boost-1_31 LIBXMLPP_INCLUDE_DIR = ${USR_INCLUDE_DIR}/libxml++-1.0 +HELIX_LIB_DIR = ${USR_LIB_DIR}/helix +HELIX_LIBS = ${HELIX_LIB_DIR}/runtlib.a \ + ${HELIX_LIB_DIR}/syslib.a \ + ${HELIX_LIB_DIR}/contlib.a \ + ${HELIX_LIB_DIR}/debuglib.a \ + ${HELIX_LIB_DIR}/utillib.a + + VPATH = ${SRC_DIR} MODULES_DIR = ${BASE_DIR}/../../modules @@ -75,6 +83,18 @@ STORAGE_LIB_DIR = ${STORAGE_DIR}/lib STORAGE_LIB = livesupport_storage STORAGE_LIB_FILE = ${STORAGE_LIB_DIR}/lib${STORAGE_LIB}.a +PLAYLIST_EXECUTOR_DIR = ${MODULES_DIR}/playlistExecutor +PLAYLIST_EXECUTOR_INCLUDE_DIR = ${PLAYLIST_EXECUTOR_DIR}/include +PLAYLIST_EXECUTOR_LIB_DIR = ${PLAYLIST_EXECUTOR_DIR}/lib +PLAYLIST_EXECUTOR_LIB = livesupport_playlist_executor +PLAYLIST_EXECUTOR_LIB_FILE = ${PLAYLIST_EXECUTOR_LIB_DIR}/lib${PLAYLIST_EXECUTOR_LIB}.a + +EVENT_SCHEDULER_DIR = ${MODULES_DIR}/eventScheduler +EVENT_SCHEDULER_INCLUDE_DIR = ${EVENT_SCHEDULER_DIR}/include +EVENT_SCHEDULER_LIB_DIR = ${EVENT_SCHEDULER_DIR}/lib +EVENT_SCHEDULER_LIB = livesupport_event_scheduler +EVENT_SCHEDULER_LIB_FILE = ${EVENT_SCHEDULER_LIB_DIR}/lib${EVENT_SCHEDULER_LIB}.a + 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 @@ -98,11 +118,15 @@ CXXFLAGS = @CXXFLAGS@ @DEFS@ @COVERAGE_CXXFLAGS@ \ -I${CORE_INCLUDE_DIR} \ -I${DB_INCLUDE_DIR} \ -I${STORAGE_INCLUDE_DIR} \ + -I${PLAYLIST_EXECUTOR_INCLUDE_DIR} \ + -I${EVENT_SCHEDULER_INCLUDE_DIR} \ -I${TMP_DIR} -LDFLAGS = @LDFLAGS@ -L${USR_LIB_DIR} \ +LDFLAGS = @LDFLAGS@ -L${USR_LIB_DIR} -L${HELIX_LIB_DIR} \ -L${CORE_LIB_DIR} \ -L${DB_LIB_DIR} \ - -L${STORAGE_LIB_DIR} + -L${STORAGE_LIB_DIR} \ + -L${PLAYLIST_EXECUTOR_LIB_DIR} \ + -L${EVENT_SCHEDULER_LIB_DIR} #------------------------------------------------------------------------------- @@ -133,12 +157,16 @@ SCHEDULER_OBJS = ${TMP_DIR}/SignalDispatcher.o \ ${TMP_DIR}/PlayLogFactory.o \ ${TMP_DIR}/PostgresqlPlayLog.o \ ${TMP_DIR}/GeneratePlayReportMethod.o \ - ${TMP_DIR}/UpdateFadeInFadeOutMethod.o + ${TMP_DIR}/UpdateFadeInFadeOutMethod.o \ + ${TMP_DIR}/PlaylistEventContainer.o \ + ${TMP_DIR}/PlaylistEvent.o SCHEDULER_EXE_OBJS = ${SCHEDULER_OBJS} \ ${TMP_DIR}/main.o -SCHEDULER_EXE_LIBS = -l${STORAGE_LIB} -l${DB_LIB} -l${CORE_LIB} \ +SCHEDULER_EXE_LIBS = -l${EVENT_SCHEDULER_LIB} -l${PLAYLIST_EXECUTOR_LIB} \ + -l${STORAGE_LIB} -l${DB_LIB} -l${CORE_LIB} \ + ${HELIX_LIBS} \ -lodbc++ -lboost_date_time-gcc \ -lxmlrpc++ -lssl -lxml++-1.0 @@ -198,6 +226,8 @@ docclean: ${RM} ${TEST_RESULTS} depclean: clean + ${MAKE} -C ${EVENT_SCHEDULER_DIR} clean + ${MAKE} -C ${PLAYLIST_EXECUTOR_DIR} clean ${MAKE} -C ${STORAGE_DIR} clean ${MAKE} -C ${DB_DIR} clean ${MAKE} -C ${CORE_DIR} clean @@ -221,6 +251,9 @@ start: ${SCHEDULER_EXE} stop: ${SCHEDULER_EXE} LD_LIBRARY_PATH=${USR_LIB_DIR} ${SCHEDULER_EXE} -c ${SCHEDULER_CFG} stop +status: ${SCHEDULER_EXE} + LD_LIBRARY_PATH=${USR_LIB_DIR} ${SCHEDULER_EXE} -c ${SCHEDULER_CFG} status + uninstall: ${SCHEDULER_EXE} LD_LIBRARY_PATH=${USR_LIB_DIR} ${SCHEDULER_EXE} -c ${SCHEDULER_CFG} \ uninstall @@ -230,6 +263,7 @@ uninstall: ${SCHEDULER_EXE} # Specific targets #------------------------------------------------------------------------------- ${SCHEDULER_EXE}: ${CORE_LIB_FILE} ${DB_LIB_FILE} ${STORAGE_LIB_FILE} \ + ${PLAYLIST_EXECUTOR_LIB_FILE} ${EVENT_SCHEDULER_LIB_FILE} \ ${SCHEDULER_EXE_OBJS} ${CXX} ${LDFLAGS} -o $@ $^ ${SCHEDULER_EXE_LIBS} @@ -240,6 +274,7 @@ ${DOXYGEN_DIR}: ${MKDIR} ${DOXYGEN_DIR} ${TEST_RUNNER}: ${CORE_LIB_FILE} ${DB_LIB_FILE} ${STORAGE_LIB_FILE} \ + ${PLAYLIST_EXECUTOR_LIB_FILE} ${EVENT_SCHEDULER_LIB_FILE} \ ${TEST_RUNNER_OBJS} ${CXX} ${LDFLAGS} -o $@ ${TEST_RUNNER_OBJS} ${TEST_RUNNER_LIBS} @@ -252,6 +287,12 @@ ${DB_LIB_FILE}: ${STORAGE_LIB_FILE}: ${MAKE} -C ${STORAGE_DIR} +${PLAYLIST_EXECUTOR_LIB_FILE}: + ${MAKE} -C ${PLAYLIST_EXECUTOR_DIR} + +${EVENT_SCHEDULER_LIB_FILE}: + ${MAKE} -C ${EVENT_SCHEDULER_DIR} + #------------------------------------------------------------------------------- # Pattern rules diff --git a/livesupport/products/scheduler/etc/configure.ac b/livesupport/products/scheduler/etc/configure.ac index 616cf167b..d4d8fc326 100644 --- a/livesupport/products/scheduler/etc/configure.ac +++ b/livesupport/products/scheduler/etc/configure.ac @@ -21,7 +21,7 @@ dnl Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA dnl dnl dnl Author : $Author: maroy $ -dnl Version : $Revision: 1.3 $ +dnl Version : $Revision: 1.4 $ dnl Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/products/scheduler/etc/configure.ac,v $ dnl----------------------------------------------------------------------------- @@ -35,7 +35,7 @@ dnl----------------------------------------------------------------------------- AC_INIT(Scheduler, 0.1, bugs@campware.org) AC_PREREQ(2.59) AC_COPYRIGHT([Copyright (c) 2004 Media Development Loan Fund under the GNU GPL]) -AC_REVISION($Revision: 1.3 $) +AC_REVISION($Revision: 1.4 $) AC_CONFIG_SRCDIR(../src/main.cxx) @@ -43,7 +43,7 @@ AC_CONFIG_HEADERS(configure.h) AC_PROG_CXX() AC_CHECK_HEADERS(sys/types.h unistd.h getopt.h signal.h sys/stat.h time.h) -AC_CHECK_HEADERS(stdio.h fcntl.h) +AC_CHECK_HEADERS(stdio.h fcntl.h pthread.h sys/time.h) dnl----------------------------------------------------------------------------- dnl enable compilaton for code coverage data diff --git a/livesupport/products/scheduler/etc/scheduler.xml b/livesupport/products/scheduler/etc/scheduler.xml index a9d403f44..872263d8b 100644 --- a/livesupport/products/scheduler/etc/scheduler.xml +++ b/livesupport/products/scheduler/etc/scheduler.xml @@ -2,7 +2,7 @@ + scheduleFactory,audioPlayer,xmlRpcDaemon) > @@ -23,6 +23,11 @@ + + + + + @@ -48,6 +53,10 @@ + + + + +#else +#error need unistd.h +#endif + +#include "LiveSupport/Core/TimeConversion.h" + +#include "PlaylistEvent.h" + + +using namespace LiveSupport::Core; +using namespace LiveSupport::Scheduler; + +/* =================================================== local data structures */ + + +/* ================================================ local constants & macros */ + + +/* =============================================== local function prototypes */ + + +/* ============================================================= module code */ + +/*------------------------------------------------------------------------------ + * Constructor. + *----------------------------------------------------------------------------*/ +PlaylistEvent :: PlaylistEvent( + Ptr::Ref audioPlayer, + Ptr::Ref storage, + Ptr::Ref scheduleEntry) + throw () +{ + this->audioPlayer = audioPlayer; + this->storage = storage; + this->scheduleEntry = scheduleEntry; +} + + +/*------------------------------------------------------------------------------ + * Initialize the event object. + *----------------------------------------------------------------------------*/ +void +PlaylistEvent :: initialize(void) throw (std::exception) +{ + playlistUrl = storage->acquirePlaylist(scheduleEntry->getPlaylistId()); +} + + +/*------------------------------------------------------------------------------ + * Initialize the event object. + *----------------------------------------------------------------------------*/ +void +PlaylistEvent :: deInitialize(void) throw () +{ + storage->releasePlaylist(scheduleEntry->getPlaylistId()); + playlistUrl.reset(); +} + + +/*------------------------------------------------------------------------------ + * Initialize the event object. + *----------------------------------------------------------------------------*/ +void +PlaylistEvent :: start(void) throw () +{ + audioPlayer->playThis(*playlistUrl); + audioPlayer->start(); +} + + +/*------------------------------------------------------------------------------ + * Initialize the event object. + *----------------------------------------------------------------------------*/ +void +PlaylistEvent :: stop(void) throw () +{ + audioPlayer->stop(); +} + diff --git a/livesupport/products/scheduler/src/PlaylistEvent.h b/livesupport/products/scheduler/src/PlaylistEvent.h new file mode 100644 index 000000000..d93f75d3b --- /dev/null +++ b/livesupport/products/scheduler/src/PlaylistEvent.h @@ -0,0 +1,215 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2004 Media Development Loan Fund + + This file is part of the LiveSupport project. + http://livesupport.campware.org/ + To report bugs, send an e-mail to bugs@campware.org + + LiveSupport is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + LiveSupport is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with LiveSupport; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + + Author : $Author: maroy $ + Version : $Revision: 1.1 $ + Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/products/scheduler/src/PlaylistEvent.h,v $ + +------------------------------------------------------------------------------*/ +#ifndef PlaylistEvent_h +#define PlaylistEvent_h + +#ifndef __cplusplus +#error This is a C++ include file +#endif + + +/* ============================================================ include files */ + +#ifdef HAVE_CONFIG_H +#include "configure.h" +#endif + +#include "LiveSupport/Core/StorageClientInterface.h" +#include "LiveSupport/PlaylistExecutor/AudioPlayerInterface.h" +#include "LiveSupport/EventScheduler/ScheduledEventInterface.h" + +#include "ScheduleEntry.h" + +namespace LiveSupport { +namespace Scheduler { + +using namespace boost::posix_time; + +using namespace LiveSupport; +using namespace LiveSupport::Core; +using namespace LiveSupport::PlaylistExecutor; +using namespace LiveSupport::EventScheduler; +using namespace LiveSupport::Scheduler; + +/* ================================================================ constants */ + + +/* =================================================================== macros */ + + +/* =============================================================== data types */ + +/** + * A scheduled event for playing a playlist. + * + * @author $Author: maroy $ + * @version $Revision: 1.1 $ + */ +class PlaylistEvent : public virtual ScheduledEventInterface +{ + private: + /** + * The audio player to play the playlist with. + */ + Ptr::Ref audioPlayer; + + /** + * The storage containing the playlist and all related audio clips. + */ + Ptr::Ref storage; + + /** + * The schedule entry this event is playing. + */ + Ptr::Ref scheduleEntry; + + /** + * The maximum time this event should get initialized in. + */ + Ptr::Ref initTime; + + /** + * The URL for this playlist file. + */ + Ptr::Ref playlistUrl; + + + public: + /** + * Constructor. + * + * @param audioPlayer the audio player to play the playlist with. + * @param storage the storage containing the playlist to play, + * and all the related audio clips. + * @param scheduleEntry the schedule entry this event is + * playing. + */ + PlaylistEvent(Ptr::Ref audioPlayer, + Ptr::Ref storage, + Ptr::Ref scheduleEntry) + throw (); + + /** + * A virtual destructor, as this class has virtual functions. + */ + virtual + ~PlaylistEvent(void) throw () + { + } + + /** + * Tell the time this event is scheduled for. + * + * @return the time this event is scheduled for. + */ + virtual Ptr::Ref + getScheduledTime(void) throw () + { + return scheduleEntry->getStartTime(); + } + + /** + * Initialize the event object. + * This should finishin at most maxTimeToInitialize() time. + * Use this call to allocate any resources that will be needed + * by the event itself. + * + * @exception std::exception on initialization problems. + * a raised exception will result in the cancellation + * of the event. + * @see #maxTimeToInitialize + */ + virtual void + initialize(void) throw (std::exception); + + /** + * The maximum time for the initalize() function to complete. + * It is the responsibility of the ScheduledEventInterface object to + * complete the initialization in that time. + * + * @return the maximum time for the initialize() function to complete. + * @see #initialize + */ + virtual Ptr::Ref + maxTimeToInitialize(void) throw () + { + return initTime; + } + + /** + * De-initialize the event object. + */ + virtual void + deInitialize(void) throw (); + + /** + * Start the event. + * This function call should start the execution of the event in + * a separate thread, and return immediately. + */ + virtual void + start(void) throw (); + + /** + * The length of the event. + * The scheduler will call stop() when this much time has passed + * after calling start(). + * + * @return the length of the event, in time. + */ + virtual Ptr::Ref + eventLength(void) throw () + { + return scheduleEntry->getPlaylength(); + } + + /** + * Stop the event. + * This function call should result in the event stopping, if + * this has not happened yet. The processing of this event should + * persue in a seperate thread, and the function itself should + * return immediately. + */ + virtual void + stop(void) throw (); +}; + + +/* ================================================= external data structures */ + + +/* ====================================================== function prototypes */ + + +} // namespace Scheduler +} // namespace LiveSupport + + +#endif // PlaylistEvent_h + diff --git a/livesupport/products/scheduler/src/PlaylistEventContainer.cxx b/livesupport/products/scheduler/src/PlaylistEventContainer.cxx new file mode 100644 index 000000000..955d50c7f --- /dev/null +++ b/livesupport/products/scheduler/src/PlaylistEventContainer.cxx @@ -0,0 +1,92 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2004 Media Development Loan Fund + + This file is part of the LiveSupport project. + http://livesupport.campware.org/ + To report bugs, send an e-mail to bugs@campware.org + + LiveSupport is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + LiveSupport is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with LiveSupport; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + + Author : $Author: maroy $ + Version : $Revision: 1.1 $ + Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/products/scheduler/src/PlaylistEventContainer.cxx,v $ + +------------------------------------------------------------------------------*/ + +/* ============================================================ include files */ + +#ifdef HAVE_CONFIG_H +#include "configure.h" +#endif + +#ifdef HAVE_UNISTD_H +#include +#else +#error need unistd.h +#endif + + +#include "PlaylistEventContainer.h" +#include "PlaylistEvent.h" + + +using namespace LiveSupport::Core; +using namespace LiveSupport::EventScheduler; +using namespace LiveSupport::Scheduler; + +/* =================================================== local data structures */ + + +/* ================================================ local constants & macros */ + + +/* =============================================== local function prototypes */ + + +/* ============================================================= module code */ + +/*------------------------------------------------------------------------------ + * Constructor. + *----------------------------------------------------------------------------*/ +PlaylistEventContainer :: PlaylistEventContainer( + Ptr::Ref storage, + Ptr::Ref schedule, + Ptr::Ref audioPlayer) + throw () +{ + this->storage = storage; + this->schedule = schedule; + this->audioPlayer = audioPlayer; +} + + +/*------------------------------------------------------------------------------ + * Return the first scheduled event after the specified timepoint + *----------------------------------------------------------------------------*/ +Ptr::Ref +PlaylistEventContainer :: getNextEvent(Ptr::Ref when) throw () +{ + Ptr::Ref entry = schedule->getNextEntry(when); + Ptr::Ref event; + + if (entry.get()) { + event.reset(new PlaylistEvent(audioPlayer, storage, entry)); + } + + return event; +} + diff --git a/livesupport/products/scheduler/src/PlaylistEventContainer.h b/livesupport/products/scheduler/src/PlaylistEventContainer.h new file mode 100644 index 000000000..9cc08b933 --- /dev/null +++ b/livesupport/products/scheduler/src/PlaylistEventContainer.h @@ -0,0 +1,139 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2004 Media Development Loan Fund + + This file is part of the LiveSupport project. + http://livesupport.campware.org/ + To report bugs, send an e-mail to bugs@campware.org + + LiveSupport is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + LiveSupport is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with LiveSupport; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + + Author : $Author: maroy $ + Version : $Revision: 1.1 $ + Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/products/scheduler/src/PlaylistEventContainer.h,v $ + +------------------------------------------------------------------------------*/ +#ifndef PlaylistEventContainer_h +#define PlaylistEventContainer_h + +#ifndef __cplusplus +#error This is a C++ include file +#endif + + +/* ============================================================ include files */ + +#ifdef HAVE_CONFIG_H +#include "configure.h" +#endif + +#include "LiveSupport/Core/StorageClientInterface.h" +#include "LiveSupport/PlaylistExecutor/AudioPlayerInterface.h" +#include "LiveSupport/EventScheduler/EventContainerInterface.h" + +#include "ScheduleInterface.h" + + +namespace LiveSupport { +namespace Scheduler { + +using namespace boost::posix_time; + +using namespace LiveSupport; +using namespace LiveSupport::Core; +using namespace LiveSupport::PlaylistExecutor; +using namespace LiveSupport::EventScheduler; + +/* ================================================================ constants */ + + +/* =================================================================== macros */ + + +/* =============================================================== data types */ + +/** + * An event container holding the scheduled playlists. + * + * @author $Author: maroy $ + * @version $Revision: 1.1 $ + */ +class PlaylistEventContainer : public virtual EventContainerInterface +{ + private: + /** + * The storage containing the playlists to play. + */ + Ptr::Ref storage; + + /** + * The schedule interface to get the events from. + */ + Ptr::Ref schedule; + + /** + * The audio player to play the playlist with. + */ + Ptr::Ref audioPlayer; + + + public: + /** + * Constructor. + * + * @param storage the storage containing the playlist and related + * audio clips + * @param schedule the schedule to get the events from. + * @param audioPlayer the audio player to play the playlists with. + */ + PlaylistEventContainer(Ptr::Ref storage, + Ptr::Ref schedule, + Ptr::Ref audioPlayer) + throw (); + + /** + * A virtual destructor, as this class has virtual functions. + */ + virtual + ~PlaylistEventContainer(void) throw () + { + } + + /** + * Return the first event after the specified timepoint. + * + * @param when return the first event after this timepoint, + * @return the first event to schedule after the specified + * timepoint. may be a reference to 0, if currently + * there are no known events after the specified time. + */ + virtual Ptr::Ref + getNextEvent(Ptr::Ref when) throw (); +}; + + +/* ================================================= external data structures */ + + +/* ====================================================== function prototypes */ + + +} // namespace Scheduler +} // namespace LiveSupport + + +#endif // PlaylistEventContainer_h + diff --git a/livesupport/products/scheduler/src/PostgresqlSchedule.cxx b/livesupport/products/scheduler/src/PostgresqlSchedule.cxx index 34b9856a7..6b1bbcac6 100644 --- a/livesupport/products/scheduler/src/PostgresqlSchedule.cxx +++ b/livesupport/products/scheduler/src/PostgresqlSchedule.cxx @@ -22,7 +22,7 @@ Author : $Author: maroy $ - Version : $Revision: 1.4 $ + Version : $Revision: 1.5 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/products/scheduler/src/PostgresqlSchedule.cxx,v $ ------------------------------------------------------------------------------*/ @@ -124,6 +124,17 @@ const std::string PostgresqlSchedule::getScheduleEntriesStmt = "(? <= starts) AND (starts < ?) " "ORDER BY starts"; +/*------------------------------------------------------------------------------ + * The SQL statement for querying the next scheduled entry from the + * specified timepoint. + * The parameters for this call are: from + * and returns the properties: id, playlist, starts, ends for the next + * schedule entry after the specified timepoint + *----------------------------------------------------------------------------*/ +const std::string PostgresqlSchedule::getNextEntryStmt = + "SELECT id, playlist, starts, ends FROM schedule WHERE ? < starts " + "ORDER BY starts"; + /*------------------------------------------------------------------------------ * The SQL statement for querying if a schedule entry exists. * Expects a single argument, the id of the schedule to check. @@ -349,6 +360,51 @@ PostgresqlSchedule :: getScheduleEntries( } +/*------------------------------------------------------------------------------ + * Get the next schedule entry after a specified timepoint + *----------------------------------------------------------------------------*/ +Ptr::Ref +PostgresqlSchedule :: getNextEntry(Ptr::Ref fromTime) + throw () +{ + Ptr::Ref conn; + Ptr::Ref result; + + try { + conn = cm->getConnection(); + Ptr::Ref timestamp; + Ptr::Ref pstmt(conn->prepareStatement( + getNextEntryStmt)); + timestamp = Conversion::ptimeToTimestamp(fromTime); + pstmt->setTimestamp(1, *timestamp); + + Ptr::Ref rs(pstmt->executeQuery()); + if (rs->next()) { + Ptr::Ref id(new UniqueId(rs->getInt(1))); + Ptr::Ref playlistId(new UniqueId(rs->getInt(2))); + + *timestamp = rs->getTimestamp(3); + Ptr::Ref startTime = Conversion::timestampToPtime(timestamp); + + *timestamp = rs->getTimestamp(4); + Ptr::Ref endTime = Conversion::timestampToPtime(timestamp); + + result.reset(new ScheduleEntry(id, playlistId, startTime, endTime)); + } + + cm->returnConnection(conn); + } catch (std::exception &e) { + if (conn) { + cm->returnConnection(conn); + } + // TODO: report error + return result; + } + + return result; +} + + /*------------------------------------------------------------------------------ * Tell if a schedule entry exists. *----------------------------------------------------------------------------*/ diff --git a/livesupport/products/scheduler/src/PostgresqlSchedule.h b/livesupport/products/scheduler/src/PostgresqlSchedule.h index e04c21044..60aa52397 100644 --- a/livesupport/products/scheduler/src/PostgresqlSchedule.h +++ b/livesupport/products/scheduler/src/PostgresqlSchedule.h @@ -22,7 +22,7 @@ Author : $Author: maroy $ - Version : $Revision: 1.5 $ + Version : $Revision: 1.6 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/products/scheduler/src/PostgresqlSchedule.h,v $ ------------------------------------------------------------------------------*/ @@ -81,7 +81,7 @@ using namespace LiveSupport::Core; * * * @author $Author: maroy $ - * @version $Revision: 1.5 $ + * @version $Revision: 1.6 $ */ class PostgresqlSchedule : public Configurable, public ScheduleInterface @@ -127,6 +127,12 @@ class PostgresqlSchedule : public Configurable, */ static const std::string getScheduleEntriesStmt; + /** + * The SQL statement for getting the next schedule entry after a + * timepoint. + */ + static const std::string getNextEntryStmt; + /** * The SQL statement for telling if a schedule entry exists. */ @@ -259,6 +265,18 @@ class PostgresqlSchedule : public Configurable, Ptr::Ref toTime) throw (); + /** + * Return the next schedule entry, after (but not including) + * the specified timepoint. + * + * @param fromTime the start of the time of the interval queried, + * inclusive + * @return the first schedule entry, after the specified timepoint. + */ + virtual Ptr::Ref + getNextEntry(Ptr::Ref fromTime) + throw (); + /** * Tell if a schedule entry exists by the give name. * diff --git a/livesupport/products/scheduler/src/PostgresqlScheduleTest.cxx b/livesupport/products/scheduler/src/PostgresqlScheduleTest.cxx index 20faec7e6..ff1cc654d 100644 --- a/livesupport/products/scheduler/src/PostgresqlScheduleTest.cxx +++ b/livesupport/products/scheduler/src/PostgresqlScheduleTest.cxx @@ -22,7 +22,7 @@ Author : $Author: maroy $ - Version : $Revision: 1.5 $ + Version : $Revision: 1.6 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/products/scheduler/src/PostgresqlScheduleTest.cxx,v $ ------------------------------------------------------------------------------*/ @@ -299,6 +299,58 @@ PostgresqlScheduleTest :: getScheduleEntriesTest(void) } +/*------------------------------------------------------------------------------ + * See if getNextEntry() returns correct entry + *----------------------------------------------------------------------------*/ +void +PostgresqlScheduleTest :: getNextEntryTest(void) + throw (CPPUNIT_NS::Exception) +{ + // create a 1 hour long playlist + Ptr::Ref playlistId = UniqueId::generateId(); + Ptr::Ref playlength(new time_duration(1, 0, 0)); + Ptr::Ref playlist(new Playlist(playlistId, playlength)); + + Ptr::Ref from; + Ptr::Ref entry; + + try { + // schedule our playlist for 2004-07-23, 10 o'clock + from.reset(new ptime(time_from_string("2004-07-23 10:00:00"))); + schedule->schedulePlaylist(playlist, from); + + // schedule our playlist for 2004-07-23, 12 o'clock + from.reset(new ptime(time_from_string("2004-07-23 12:00:00"))); + schedule->schedulePlaylist(playlist, from); + + // schedule our playlist for 2004-07-23, 14 o'clock + from.reset(new ptime(time_from_string("2004-07-23 14:00:00"))); + schedule->schedulePlaylist(playlist, from); + + // see what gives after 2004-07-23 09:00:00 + from.reset(new ptime(time_from_string("2004-07-23 09:00:00"))); + entry = schedule->getNextEntry(from); + CPPUNIT_ASSERT(entry.get()); + // see that it is a single entry starting from 10 to 11 o'clock + CPPUNIT_ASSERT(*(entry->getPlaylistId()) == *(playlist->getId())); + from.reset(new ptime(time_from_string("2004-07-23 10:00:00"))); + CPPUNIT_ASSERT(*(entry->getStartTime()) == *from); + + // see what gives after 2004-07-23 10:00:00 + from.reset(new ptime(time_from_string("2004-07-23 10:00:00"))); + entry = schedule->getNextEntry(from); + CPPUNIT_ASSERT(entry.get()); + // see that it is a single entry starting from 10 to 11 o'clock + CPPUNIT_ASSERT(*(entry->getPlaylistId()) == *(playlist->getId())); + from.reset(new ptime(time_from_string("2004-07-23 12:00:00"))); + CPPUNIT_ASSERT(*(entry->getStartTime()) == *from); + + } catch (std::invalid_argument &e) { + CPPUNIT_FAIL(e.what()); + } +} + + /*------------------------------------------------------------------------------ * See if scheduleEntryExists() returns correct results *----------------------------------------------------------------------------*/ diff --git a/livesupport/products/scheduler/src/PostgresqlScheduleTest.h b/livesupport/products/scheduler/src/PostgresqlScheduleTest.h index ca60ea7b8..6ac281cc5 100644 --- a/livesupport/products/scheduler/src/PostgresqlScheduleTest.h +++ b/livesupport/products/scheduler/src/PostgresqlScheduleTest.h @@ -22,7 +22,7 @@ Author : $Author: maroy $ - Version : $Revision: 1.4 $ + Version : $Revision: 1.5 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/products/scheduler/src/PostgresqlScheduleTest.h,v $ ------------------------------------------------------------------------------*/ @@ -64,7 +64,7 @@ using namespace LiveSupport::Core; * Unit test for the PostgresqlSchedule class. * * @author $Author: maroy $ - * @version $Revision: 1.4 $ + * @version $Revision: 1.5 $ * @see PostgresqlSchedule */ class PostgresqlScheduleTest : public CPPUNIT_NS::TestFixture @@ -74,6 +74,7 @@ class PostgresqlScheduleTest : public CPPUNIT_NS::TestFixture CPPUNIT_TEST(simpleScheduleTest); CPPUNIT_TEST(scheduleAndQueryTest); CPPUNIT_TEST(getScheduleEntriesTest); + CPPUNIT_TEST(getNextEntryTest); CPPUNIT_TEST(scheduleEntryExistsTest); CPPUNIT_TEST(removeFromScheduleTest); CPPUNIT_TEST(rescheduleTest); @@ -126,6 +127,15 @@ class PostgresqlScheduleTest : public CPPUNIT_NS::TestFixture void getScheduleEntriesTest(void) throw (CPPUNIT_NS::Exception); + /** + * Schedule some playlists, then get the some playlists by + * specifying a time. + * + * @exception CPPUNIT_NS::Exception on test failures. + */ + void + getNextEntryTest(void) throw (CPPUNIT_NS::Exception); + /** * Schedule some playlists, then check if they exist. * diff --git a/livesupport/products/scheduler/src/ScheduleInterface.h b/livesupport/products/scheduler/src/ScheduleInterface.h index c42819242..17e4a5a9d 100644 --- a/livesupport/products/scheduler/src/ScheduleInterface.h +++ b/livesupport/products/scheduler/src/ScheduleInterface.h @@ -22,7 +22,7 @@ Author : $Author: maroy $ - Version : $Revision: 1.4 $ + Version : $Revision: 1.5 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/products/scheduler/src/ScheduleInterface.h,v $ ------------------------------------------------------------------------------*/ @@ -70,7 +70,7 @@ using namespace LiveSupport::Core; * The generic interface for the component scheduling events. * * @author $Author: maroy $ - * @version $Revision: 1.4 $ + * @version $Revision: 1.5 $ */ class ScheduleInterface : virtual public Installable { @@ -117,6 +117,19 @@ class ScheduleInterface : virtual public Installable throw () = 0; + /** + * Return the next schedule entry, after (but not including) + * the specified timepoint. + * + * @param fromTime the start of the time of the interval queried, + * inclusive + * @return the first schedule entry, after the specified timepoint. + */ + virtual Ptr::Ref + getNextEntry(Ptr::Ref fromTime) + throw () + = 0; + /** * Tell if a schedule entry exists by the give name. * diff --git a/livesupport/products/scheduler/src/SchedulerDaemon.cxx b/livesupport/products/scheduler/src/SchedulerDaemon.cxx index 1d78afd3d..5674a22d5 100644 --- a/livesupport/products/scheduler/src/SchedulerDaemon.cxx +++ b/livesupport/products/scheduler/src/SchedulerDaemon.cxx @@ -22,7 +22,7 @@ Author : $Author: maroy $ - Version : $Revision: 1.5 $ + Version : $Revision: 1.6 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/products/scheduler/src/SchedulerDaemon.cxx,v $ ------------------------------------------------------------------------------*/ @@ -51,12 +51,19 @@ #include #include +#include + #include "LiveSupport/Db/ConnectionManagerFactory.h" #include "LiveSupport/Storage/StorageClientFactory.h" +#include "LiveSupport/PlaylistExecutor/AudioPlayerFactory.h" #include "ScheduleFactory.h" #include "SchedulerDaemon.h" +#include "PlaylistEventContainer.h" +using namespace boost::posix_time; + +using namespace LiveSupport; using namespace LiveSupport::Db; using namespace LiveSupport::Storage; using namespace LiveSupport::Scheduler; @@ -88,6 +95,20 @@ static const std::string xmlRpcDaemonConfElement = "xmlRpcDaemon"; /* ============================================================= module code */ +/*------------------------------------------------------------------------------ + * The default constructor. + *----------------------------------------------------------------------------*/ +SchedulerDaemon :: SchedulerDaemon (void) throw () + : XmlRpcDaemon() +{ + uploadPlaylistMethod.reset(new UploadPlaylistMethod()); + displayScheduleMethod.reset(new DisplayScheduleMethod()); + displayPlaylistMethod.reset(new DisplayPlaylistMethod()); + removeFromScheduleMethod.reset(new RemoveFromScheduleMethod()); + rescheduleMethod.reset(new RescheduleMethod()); +} + + /*------------------------------------------------------------------------------ * Return the singleton instnace. *----------------------------------------------------------------------------*/ @@ -136,6 +157,14 @@ SchedulerDaemon :: configure(const xmlpp::Element & element) Ptr::Ref scf = StorageClientFactory::getInstance(); scf->configure( *((const xmlpp::Element*) *(nodes.begin())) ); + // configure the AudioPlayerFactory + nodes = element.get_children(AudioPlayerFactory::getConfigElementName()); + if (nodes.size() < 1) { + throw std::invalid_argument("no audioPlayer element"); + } + Ptr::Ref apf = AudioPlayerFactory::getInstance(); + apf->configure( *((const xmlpp::Element*) *(nodes.begin())) ); + // configure the ScheduleFactory nodes = element.get_children(ScheduleFactory::getConfigElementName()); if (nodes.size() < 1) { @@ -151,6 +180,21 @@ SchedulerDaemon :: configure(const xmlpp::Element & element) } configureXmlRpcDaemon( *((const xmlpp::Element*) *(nodes.begin())) ); + + // do some initialization, using the configured objects + audioPlayer = apf->getAudioPlayer(); + + Ptr::Ref eventContainer; + Ptr::Ref granularity; + eventContainer.reset(new PlaylistEventContainer(scf->getStorageClient(), + sf->getSchedule(), + audioPlayer)); + // TODO: read granularity from config file + granularity.reset(new time_duration(seconds(30))); + + eventScheduler.reset( + new LiveSupport::EventScheduler::EventScheduler(eventContainer, + granularity)); } @@ -194,3 +238,32 @@ SchedulerDaemon :: uninstall(void) throw (std::exception) } +/*------------------------------------------------------------------------------ + * Start the scheduler daemon. + *----------------------------------------------------------------------------*/ +void +SchedulerDaemon :: start(void) throw (std::logic_error) +{ + std::cerr << "SchedulerDaemon::start #1" << std::endl; + audioPlayer->initialize(); + std::cerr << "SchedulerDaemon::start #2" << std::endl; + eventScheduler->start(); + std::cerr << "SchedulerDaemon::start #3" << std::endl; + XmlRpcDaemon::start(); + std::cerr << "SchedulerDaemon::start #4" << std::endl; +} + + +/*------------------------------------------------------------------------------ + * Stop the scheduler daemon. + *----------------------------------------------------------------------------*/ +void +SchedulerDaemon :: stop(void) throw (std::logic_error) +{ + eventScheduler->stop(); + audioPlayer->deInitialize(); + + XmlRpcDaemon::stop(); +} + + diff --git a/livesupport/products/scheduler/src/SchedulerDaemon.h b/livesupport/products/scheduler/src/SchedulerDaemon.h index f618fea57..85a30247b 100644 --- a/livesupport/products/scheduler/src/SchedulerDaemon.h +++ b/livesupport/products/scheduler/src/SchedulerDaemon.h @@ -22,7 +22,7 @@ Author : $Author: maroy $ - Version : $Revision: 1.6 $ + Version : $Revision: 1.7 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/products/scheduler/src/SchedulerDaemon.h,v $ ------------------------------------------------------------------------------*/ @@ -60,6 +60,8 @@ #include "LiveSupport/Core/Ptr.h" #include "LiveSupport/Core/Installable.h" #include "LiveSupport/Core/Configurable.h" +#include "LiveSupport/PlaylistExecutor/AudioPlayerInterface.h" +#include "LiveSupport/EventScheduler/EventScheduler.h" #include "UploadPlaylistMethod.h" #include "DisplayScheduleMethod.h" #include "DisplayPlaylistMethod.h" @@ -71,7 +73,9 @@ namespace LiveSupport { namespace Scheduler { +using namespace LiveSupport; using namespace LiveSupport::Core; +using namespace LiveSupport::PlaylistExecutor; /* ================================================================ constants */ @@ -120,7 +124,7 @@ using namespace LiveSupport::Core; * * * @author $Author: maroy $ - * @version $Revision: 1.6 $ + * @version $Revision: 1.7 $ * @see ConnectionManagerFactory * @see StorageClientFactory * @see ScheduleFactory @@ -137,6 +141,16 @@ class SchedulerDaemon : public Installable, */ static Ptr::Ref schedulerDaemon; + /** + * The event scheduler. + */ + Ptr::Ref eventScheduler; + + /** + * The audio player. + */ + Ptr::Ref audioPlayer; + /** * The UploadPlaylistMethod the daemon is providing. */ @@ -165,15 +179,8 @@ class SchedulerDaemon : public Installable, /** * Default constructor. */ - SchedulerDaemon (void) throw () - : XmlRpcDaemon() - { - uploadPlaylistMethod.reset(new UploadPlaylistMethod()); - displayScheduleMethod.reset(new DisplayScheduleMethod()); - displayPlaylistMethod.reset(new DisplayPlaylistMethod()); - removeFromScheduleMethod.reset(new RemoveFromScheduleMethod()); - rescheduleMethod.reset(new RescheduleMethod()); - } + SchedulerDaemon (void) throw (); + protected: @@ -237,6 +244,25 @@ class SchedulerDaemon : public Installable, */ virtual void uninstall(void) throw (std::exception); + + /** + * Start the daemon. + * + * @exception std::logic_error if the daemon has not + * yet been configured. + */ + virtual void + start (void) throw (std::logic_error); + + /** + * Stop the daemon. + * + * @exception std::logic_error if the daemon has not + * yet been configured. + */ + virtual void + stop (void) throw (std::logic_error); + }; diff --git a/livesupport/products/scheduler/src/XmlRpcDaemon.h b/livesupport/products/scheduler/src/XmlRpcDaemon.h index 27c91a0a4..eb3899dbb 100644 --- a/livesupport/products/scheduler/src/XmlRpcDaemon.h +++ b/livesupport/products/scheduler/src/XmlRpcDaemon.h @@ -22,7 +22,7 @@ Author : $Author: maroy $ - Version : $Revision: 1.2 $ + Version : $Revision: 1.3 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/products/scheduler/src/XmlRpcDaemon.h,v $ ------------------------------------------------------------------------------*/ @@ -119,7 +119,7 @@ using namespace LiveSupport::Core; * * * @author $Author: maroy $ - * @version $Revision: 1.2 $ + * @version $Revision: 1.3 $ */ class XmlRpcDaemon { @@ -371,7 +371,7 @@ class XmlRpcDaemon * @exception std::logic_error if the daemon has not * yet been configured. */ - void + virtual void start (void) throw (std::logic_error); /** @@ -392,7 +392,7 @@ class XmlRpcDaemon * @exception std::logic_error if the daemon has not * yet been configured. */ - void + virtual void stop (void) throw (std::logic_error); /** diff --git a/livesupport/products/scheduler/src/main.cxx b/livesupport/products/scheduler/src/main.cxx index eb3acce7a..9d5c434f1 100644 --- a/livesupport/products/scheduler/src/main.cxx +++ b/livesupport/products/scheduler/src/main.cxx @@ -22,7 +22,7 @@ Author : $Author: maroy $ - Version : $Revision: 1.2 $ + Version : $Revision: 1.3 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/products/scheduler/src/main.cxx,v $ ------------------------------------------------------------------------------*/ @@ -161,21 +161,21 @@ int main ( int argc, case 'h': printUsage(argv[0], std::cout); - return 0; + exit(EXIT_SUCCESS); case 'v': printVersion(std::cout); - return 0; + exit(EXIT_SUCCESS); default: printUsage(argv[0], std::cout); - return 1; + exit(EXIT_FAILURE); } } if (optind != argc - 1) { printUsage(argv[0], std::cout); - return 1; + exit(EXIT_FAILURE); } std::cerr << "using config file '" << configFileName << '\'' << std::endl; @@ -190,11 +190,11 @@ int main ( int argc, } catch (std::invalid_argument &e) { std::cerr << "semantic error in configuration file" << std::endl << e.what() << std::endl; - return 1; + exit(EXIT_FAILURE); } catch (xmlpp::exception &e) { std::cerr << "error parsing configuration file" << std::endl << e.what() << std::endl; - return 1; + exit(EXIT_FAILURE); } daemon->setBackground(!debugMode); @@ -213,10 +213,10 @@ int main ( int argc, daemon->uninstall(); } else { printUsage(argv[0], std::cout); - return 1; + exit(EXIT_FAILURE); } - return 0; + exit(EXIT_SUCCESS); }