diff --git a/livesupport/modules/playlistExecutor/etc/Makefile.in b/livesupport/modules/playlistExecutor/etc/Makefile.in index 7dd2ee5a0..87b1912fe 100644 --- a/livesupport/modules/playlistExecutor/etc/Makefile.in +++ b/livesupport/modules/playlistExecutor/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.6 $ +# Author : $Author: fgerlits $ +# Version : $Revision: 1.7 $ # Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/playlistExecutor/etc/Makefile.in,v $ # # @configure_input@ @@ -77,6 +77,8 @@ VPATH = ${SRC_DIR} LIBXMLPP_CFLAGS=@LIBXMLPP_CFLAGS@ LIBXMLPP_LIBS=@LIBXMLPP_LIBS@ +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 @@ -105,6 +107,7 @@ CXXFLAGS = @CXXFLAGS@ @DEFS@ @COVERAGE_CXXFLAGS@ -pthread \ -I${INCLUDE_DIR} -I${TMP_DIR} LDFLAGS = @LDFLAGS@ -pthread \ ${LIBXMLPP_LIBS} \ + ${TAGLIB_LIBS} \ -L${USR_LIB_DIR} \ -L${CORE_LIB_DIR} \ -L${HELIX_LIB_DIR} \ @@ -126,8 +129,8 @@ TEST_RUNNER_OBJS = ${TMP_DIR}/TestRunner.o \ ${TMP_DIR}/HelixPlayerTest.o \ ${TMP_DIR}/AudioPlayerFactoryTest.o TEST_RUNNER_LIBS = -l${PLAYLIST_EXECUTOR_LIB} -l${CORE_LIB} \ - ${HELIX_LIBS} \ - -lcppunit -ldl -lm + ${HELIX_LIBS} ${TAGLIB_LIBS} \ + -lcppunit -ldl -lm -lxmlrpc++ #------------------------------------------------------------------------------- diff --git a/livesupport/modules/playlistExecutor/etc/playlist.xml b/livesupport/modules/playlistExecutor/etc/playlist.xml new file mode 100644 index 000000000..160530ef1 --- /dev/null +++ b/livesupport/modules/playlistExecutor/etc/playlist.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + +]> + + + + + + + + + + + + + + + diff --git a/livesupport/modules/playlistExecutor/src/HelixPlayer.cxx b/livesupport/modules/playlistExecutor/src/HelixPlayer.cxx index 0433236bd..2b832cfaf 100644 --- a/livesupport/modules/playlistExecutor/src/HelixPlayer.cxx +++ b/livesupport/modules/playlistExecutor/src/HelixPlayer.cxx @@ -21,8 +21,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Author : $Author: maroy $ - Version : $Revision: 1.10 $ + Author : $Author: fgerlits $ + Version : $Revision: 1.11 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/playlistExecutor/src/Attic/HelixPlayer.cxx,v $ ------------------------------------------------------------------------------*/ @@ -278,7 +278,7 @@ void HelixPlayer :: start(void) throw (std::logic_error) { if (player->GetSourceCount() == 0) { - throw std::logic_error("HelixPlayer::playThis() not called yet"); + throw std::logic_error("HelixPlayer::open() not called yet"); } player->Begin(); playing = true; @@ -376,3 +376,97 @@ DLLAccessPath* GetDLLAccessPath(void) } +/*------------------------------------------------------------------------------ + * Play a playlist, with simulated fading. + *----------------------------------------------------------------------------*/ +void +HelixPlayer :: openAndStartPlaylist(Ptr::Ref playlist) + throw (std::invalid_argument, + std::logic_error, + std::runtime_error) +{ + if (!playlist || !playlist->getUri()) { + throw std::invalid_argument("no playlist SMIL file found"); + } + open(*playlist->getUri()); // may throw invalid_argument + + bool hasFadeInfo = false; + int numberOfPlaylistElements = 0; + Playlist::const_iterator it = playlist->begin(); + while (it != playlist->end()) { + ++numberOfPlaylistElements; + if (it->second->getFadeInfo()) { + hasFadeInfo = true; + } + ++it; + } + + start(); // may throw logic_error + if (!numberOfPlaylistElements || !hasFadeInfo) { + return; + } + + IHXAudioPlayer* audioPlayer = 0; + if (player->QueryInterface(IID_IHXAudioPlayer, (void**)&audioPlayer) + != HXR_OK + || !audioPlayer) { + throw std::runtime_error("can't get IHXAudioPlayer interface"); + } + + IHXAudioCrossFade* crossFade = 0; + if (audioPlayer->QueryInterface(IID_IHXAudioCrossFade, (void**)&crossFade) + != HXR_OK + || !crossFade) { + throw std::runtime_error("can't get IHXAudioCrossFade interface"); + } + + Ptr::Ref sleepT(new time_duration(microseconds(10))); + + IHXAudioStream* audioStream[numberOfPlaylistElements]; + for (int i = 0; i < numberOfPlaylistElements; i++) { + do { + TimeConversion::sleep(sleepT); + audioStream[i] = audioPlayer->GetAudioStream(i); + } while (!audioStream[i]); + } + + it = playlist->begin(); + + sleepT.reset(new time_duration(seconds(2))); + TimeConversion::sleep(sleepT); + + for (int i = 1; i < numberOfPlaylistElements; i++) { + + Ptr::Ref playlistElement = it->second; + if (!playlistElement->getFadeInfo()) { + ++it; + continue; + } + + // we assume i-th fade out is the same as (i+1)-st fade in + unsigned long crossFadeLength = playlistElement + ->getFadeInfo() + ->getFadeOut() + ->total_milliseconds(); + unsigned long fadeOutAt = playlistElement->getRelativeOffset() + ->total_milliseconds() + + playlistElement->getPlayable() + ->getPlaylength() + ->total_milliseconds() + - crossFadeLength; + +//std::cerr << "fadeOutAt: " << fadeOutAt << "\n" +// << "crossFadeLength: " << crossFadeLength << "\n"; + crossFade->CrossFade(audioStream[i-1], audioStream[i], + fadeOutAt, fadeOutAt, crossFadeLength); + + ++it; + } + + for (int i = 0; i < numberOfPlaylistElements; i++) { + HX_RELEASE(audioStream[i]); + } + HX_RELEASE(crossFade); + HX_RELEASE(audioPlayer); +} + diff --git a/livesupport/modules/playlistExecutor/src/HelixPlayer.h b/livesupport/modules/playlistExecutor/src/HelixPlayer.h index 8f5882e81..94c4d370d 100644 --- a/livesupport/modules/playlistExecutor/src/HelixPlayer.h +++ b/livesupport/modules/playlistExecutor/src/HelixPlayer.h @@ -21,8 +21,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Author : $Author: maroy $ - Version : $Revision: 1.8 $ + Author : $Author: fgerlits $ + Version : $Revision: 1.9 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/playlistExecutor/src/Attic/HelixPlayer.h,v $ ------------------------------------------------------------------------------*/ @@ -52,7 +52,7 @@ #include "ErrorSink.h" #include "AuthenticationManager.h" #include "ClientContext.h" - +#include "LiveSupport/Core/Playlist.h" namespace LiveSupport { namespace PlaylistExecutor { @@ -90,8 +90,8 @@ using namespace LiveSupport::Core; * * * - * @author $Author: maroy $ - * @version $Revision: 1.8 $ + * @author $Author: fgerlits $ + * @version $Revision: 1.9 $ */ class HelixPlayer : virtual public Configurable, virtual public AudioPlayerInterface, @@ -236,7 +236,7 @@ class HelixPlayer : virtual public Configurable, * will be accessed automatically. * Note: this call will not start playing! You will * have to call the start() function to begin playing. - * Always close any opened resources with a call to close(). + * Always close any opened resource with a call to close(). * * @param fileUrl a URL to a file * @exception std::invalid_argument if the supplied fileUrl @@ -258,12 +258,12 @@ class HelixPlayer : virtual public Configurable, /** * Start playing. * This call will start playing the active playlist, which was - * set by a previous call to playThis(). + * set by a previous call to open(). * Playing can be stopped by calling stop(). * * @exception std::logic_error if there was no previous call to - * playThis(). - * @see #playThis + * open(). + * @see #open * @see #stop */ virtual void @@ -326,6 +326,23 @@ class HelixPlayer : virtual public Configurable, */ virtual void setVolume(unsigned int volume) throw (); + + /** + * Play a playlist, with simulated fading. + * + * @param playlist the Playlist object to be played. + * @exception std::invalid_argument playlist is invalid (e.g., + * does not have a URI field, or there is no valid + * SMIL file at the given URI). + * @exception std::logic_error thrown by start() if open() was + * unsuccessful, but returned normally (never happens) + * @exception std::runtime_error on errors thrown by the helix player + */ + void + openAndStartPlaylist(Ptr::Ref playlist) + throw (std::invalid_argument, + std::logic_error, + std::runtime_error); }; diff --git a/livesupport/modules/playlistExecutor/src/HelixPlayerTest.cxx b/livesupport/modules/playlistExecutor/src/HelixPlayerTest.cxx index be93a459e..25ab8065d 100644 --- a/livesupport/modules/playlistExecutor/src/HelixPlayerTest.cxx +++ b/livesupport/modules/playlistExecutor/src/HelixPlayerTest.cxx @@ -21,8 +21,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Author : $Author: maroy $ - Version : $Revision: 1.8 $ + Author : $Author: fgerlits $ + Version : $Revision: 1.9 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/playlistExecutor/src/Attic/HelixPlayerTest.cxx,v $ ------------------------------------------------------------------------------*/ @@ -63,6 +63,12 @@ CPPUNIT_TEST_SUITE_REGISTRATION(HelixPlayerTest); */ static const std::string configFileName = "etc/helixPlayer.xml"; +/** + * The name of the configuration file for the test playlist in the + * openAndStartPlaylist() method. + */ +static const std::string playlistConfigFileName = "etc/playlist.xml"; + /* =============================================== local function prototypes */ @@ -382,3 +388,46 @@ HelixPlayerTest :: smilSoundAnimationTest(void) } +/*------------------------------------------------------------------------------ + * Test different SMIL file features + *----------------------------------------------------------------------------*/ +void +HelixPlayerTest :: animationWorkaroundTest(void) + throw (CPPUNIT_NS::Exception) +{ + Ptr::Ref playlist; + + try { + Ptr::Ref parser( + new xmlpp::DomParser(playlistConfigFileName, true)); + const xmlpp::Document * document = parser->get_document(); + const xmlpp::Element * root = document->get_root_node(); + + playlist.reset(new Playlist()); + playlist->configure(*root); + + } catch (std::invalid_argument &e) { + std::cerr << "semantic error in configuration file" << std::endl; + } catch (xmlpp::exception &e) { + std::cerr << e.what() << std::endl; + } + + CPPUNIT_ASSERT(playlist); + CPPUNIT_ASSERT(playlist->getId()); + + Ptr::Ref uri(new std::string("file:var/playlist.smil")); + playlist->setUri(uri); + + CPPUNIT_ASSERT_NO_THROW(helixPlayer->initialize()); + CPPUNIT_ASSERT_NO_THROW(helixPlayer->openAndStartPlaylist(playlist)); + CPPUNIT_ASSERT(helixPlayer->isPlaying()); + + Ptr::Ref sleepT(new time_duration(microseconds(10))); + while (helixPlayer->isPlaying()) { + TimeConversion::sleep(sleepT); + } + CPPUNIT_ASSERT(!helixPlayer->isPlaying()); + helixPlayer->close(); + + helixPlayer->deInitialize(); +} diff --git a/livesupport/modules/playlistExecutor/src/HelixPlayerTest.h b/livesupport/modules/playlistExecutor/src/HelixPlayerTest.h index a865ae16b..5fbaca722 100644 --- a/livesupport/modules/playlistExecutor/src/HelixPlayerTest.h +++ b/livesupport/modules/playlistExecutor/src/HelixPlayerTest.h @@ -22,7 +22,7 @@ Author : $Author: fgerlits $ - Version : $Revision: 1.7 $ + Version : $Revision: 1.8 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/playlistExecutor/src/Attic/HelixPlayerTest.h,v $ ------------------------------------------------------------------------------*/ @@ -58,7 +58,7 @@ namespace PlaylistExecutor { * Unit test for the HelixPlayer class. * * @author $Author: fgerlits $ - * @version $Revision: 1.7 $ + * @version $Revision: 1.8 $ * @see HelixPlayer */ class HelixPlayerTest : public CPPUNIT_NS::TestFixture @@ -75,6 +75,7 @@ class HelixPlayerTest : public CPPUNIT_NS::TestFixture // CPPUNIT_TEST(smilParallelTest3); // CPPUNIT_TEST(smilParallelTest4); // CPPUNIT_TEST(smilSoundAnimationTest); + CPPUNIT_TEST(animationWorkaroundTest); CPPUNIT_TEST_SUITE_END(); private: @@ -185,6 +186,14 @@ class HelixPlayerTest : public CPPUNIT_NS::TestFixture void smilSoundAnimationTest(void) throw (CPPUNIT_NS::Exception); + /** + * Test the openAndStartPlaylist() method. + * + * @exception CPPUNIT_NS::Exception on test failures. + */ + void + animationWorkaroundTest(void) throw (CPPUNIT_NS::Exception); + public: /** diff --git a/livesupport/modules/playlistExecutor/var/playlist.smil b/livesupport/modules/playlistExecutor/var/playlist.smil new file mode 100644 index 000000000..6f4f48b8a --- /dev/null +++ b/livesupport/modules/playlistExecutor/var/playlist.smil @@ -0,0 +1,10 @@ + + + + + + diff --git a/livesupport/modules/playlistExecutor/var/test10001.mp3 b/livesupport/modules/playlistExecutor/var/test10001.mp3 new file mode 100644 index 000000000..5fe526402 Binary files /dev/null and b/livesupport/modules/playlistExecutor/var/test10001.mp3 differ diff --git a/livesupport/modules/playlistExecutor/var/test10002.mp3 b/livesupport/modules/playlistExecutor/var/test10002.mp3 new file mode 100644 index 000000000..1219a9056 Binary files /dev/null and b/livesupport/modules/playlistExecutor/var/test10002.mp3 differ diff --git a/livesupport/modules/playlistExecutor/var/test10003.mp3 b/livesupport/modules/playlistExecutor/var/test10003.mp3 new file mode 100644 index 000000000..c0685a294 Binary files /dev/null and b/livesupport/modules/playlistExecutor/var/test10003.mp3 differ