diff --git a/livesupport/modules/playlistExecutor/include/LiveSupport/PlaylistExecutor/AudioPlayerInterface.h b/livesupport/modules/playlistExecutor/include/LiveSupport/PlaylistExecutor/AudioPlayerInterface.h index 46e9d037f..ca30e27cd 100644 --- a/livesupport/modules/playlistExecutor/include/LiveSupport/PlaylistExecutor/AudioPlayerInterface.h +++ b/livesupport/modules/playlistExecutor/include/LiveSupport/PlaylistExecutor/AudioPlayerInterface.h @@ -22,7 +22,7 @@ Author : $Author: maroy $ - Version : $Revision: 1.3 $ + Version : $Revision: 1.4 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/playlistExecutor/include/LiveSupport/PlaylistExecutor/AudioPlayerInterface.h,v $ ------------------------------------------------------------------------------*/ @@ -43,11 +43,17 @@ #include #include +#include + +#include "LiveSupport/Core/Ptr.h" + namespace LiveSupport { namespace PlaylistExecutor { -using namespace LiveSupport; +using namespace boost; + +using namespace LiveSupport::Core; /* ================================================================ constants */ @@ -61,7 +67,7 @@ using namespace LiveSupport; * A generic interface for playing audio files. * * @author $Author: maroy $ - * @version $Revision: 1.3 $ + * @version $Revision: 1.4 $ */ class AudioPlayerInterface { @@ -95,16 +101,36 @@ class AudioPlayerInterface * 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(). * * @param fileUrl a URL to a file * @exception std::invalid_argument if the supplied fileUrl * seems to be invalid. + * @see #close * @see #start */ virtual void - playThis(const std::string fileUrl) throw (std::invalid_argument) + open(const std::string fileUrl) throw (std::invalid_argument) = 0; + /** + * Close an audio source that was opened. + * + * @see #open + */ + virtual void + close(void) throw () = 0; + + /** + * Get the length of the currently opened audio clip. + * This function waits as long as necessary to get the length. + * + * @return the length of the currently playing audio clip, or 0, + * if nothing is openned. + */ + virtual Ptr::Ref + getPlaylength(void) throw () = 0; + /** * Start playing. * This call will start playing the active playlist, which was diff --git a/livesupport/modules/playlistExecutor/src/AdviseSink.cxx b/livesupport/modules/playlistExecutor/src/AdviseSink.cxx index 417795faf..257f08b64 100644 --- a/livesupport/modules/playlistExecutor/src/AdviseSink.cxx +++ b/livesupport/modules/playlistExecutor/src/AdviseSink.cxx @@ -22,7 +22,7 @@ Author : $Author: maroy $ - Version : $Revision: 1.1 $ + Version : $Revision: 1.2 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/playlistExecutor/src/Attic/AdviseSink.cxx,v $ ------------------------------------------------------------------------------*/ @@ -37,6 +37,7 @@ #include +#include "HelixPlayer.h" #include "AdviseSink.h" using namespace LiveSupport::PlaylistExecutor; @@ -56,12 +57,15 @@ using namespace LiveSupport::PlaylistExecutor; /*------------------------------------------------------------------------------ * Construct the advise sink *----------------------------------------------------------------------------*/ -AdviseSink::AdviseSink(IUnknown * pUnknown) throw () +AdviseSink::AdviseSink(IUnknown * pUnknown, + Ptr::Ref helixPlayer) throw () : lRefCount(0) , pUnknown(NULL) , pRegistry(NULL) , pScheduler(NULL) { + this->helixPlayer = helixPlayer; + if (pUnknown) { this->pUnknown = pUnknown; this->pUnknown->AddRef(); @@ -168,6 +172,7 @@ STDMETHODIMP AdviseSink::OnPosLength(UINT32 ulPosition, UINT32 ulLength) throw () { + helixPlayer->setPlaylength(ulLength); return HXR_OK; } diff --git a/livesupport/modules/playlistExecutor/src/AdviseSink.h b/livesupport/modules/playlistExecutor/src/AdviseSink.h index 1ebc3cf1e..27a1ab6da 100644 --- a/livesupport/modules/playlistExecutor/src/AdviseSink.h +++ b/livesupport/modules/playlistExecutor/src/AdviseSink.h @@ -22,7 +22,7 @@ Author : $Author: maroy $ - Version : $Revision: 1.1 $ + Version : $Revision: 1.2 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/playlistExecutor/src/Attic/AdviseSink.h,v $ ------------------------------------------------------------------------------*/ @@ -46,11 +46,13 @@ #include #include +#include "LiveSupport/Core/Ptr.h" + namespace LiveSupport { namespace PlaylistExecutor { -using namespace LiveSupport; +using namespace LiveSupport::Core; /* ================================================================ constants */ @@ -61,12 +63,15 @@ using namespace LiveSupport; /* =============================================================== data types */ +class HelixPlayer; + + /** * A Helix client advise sink, receiving notifications on the status * of the client playing. * * @author $Author: maroy $ - * @version $Revision: 1.1 $ + * @version $Revision: 1.2 $ */ class AdviseSink : public IHXClientAdviseSink { @@ -100,15 +105,24 @@ class AdviseSink : public IHXClientAdviseSink * The time playing os stopped. */ UINT32 ulStopTime; - - + + /** + * The HelixPlayer object this advise sink is associated with. + */ + Ptr::Ref helixPlayer; + + public: /** * Constructor + * + * @param pUknown the Helix object to initialize this sink with + * @param helixPlayer the HelixPlayer object this sink is + * associated with */ - AdviseSink(IUnknown * pUnknown) throw (); - + AdviseSink(IUnknown * pUnknown, + Ptr::Ref helixPlayer) throw (); /** * Destructor. diff --git a/livesupport/modules/playlistExecutor/src/ClientContext.cxx b/livesupport/modules/playlistExecutor/src/ClientContext.cxx index 4e70d6de6..2fb8a46be 100644 --- a/livesupport/modules/playlistExecutor/src/ClientContext.cxx +++ b/livesupport/modules/playlistExecutor/src/ClientContext.cxx @@ -22,7 +22,7 @@ Author : $Author: maroy $ - Version : $Revision: 1.1 $ + Version : $Revision: 1.2 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/playlistExecutor/src/Attic/ClientContext.cxx,v $ ------------------------------------------------------------------------------*/ @@ -42,6 +42,7 @@ #include "ErrorSink.h" #include "AuthenticationManager.h" #include "ClientContext.h" +#include "HelixPlayer.h" using namespace LiveSupport::PlaylistExecutor; @@ -61,13 +62,14 @@ using namespace LiveSupport::PlaylistExecutor; /*------------------------------------------------------------------------------ * Construct the Client Context *----------------------------------------------------------------------------*/ -ClientContext::ClientContext() throw () +ClientContext::ClientContext(Ptr::Ref helixPlayer) throw () : lRefCount(0) , pClientSink(NULL) , pErrorSink(NULL) , pAuthMgr(NULL) , pDefaultPrefs(NULL) { + this->helixPlayer = helixPlayer; } @@ -90,7 +92,7 @@ ClientContext::Init(IUnknown * pUnknown, { char* pszCipher = NULL; - pClientSink = new AdviseSink(pUnknown); + pClientSink = new AdviseSink(pUnknown, helixPlayer); pErrorSink = new ErrorSink(pUnknown); pAuthMgr = new AuthenticationManager(); diff --git a/livesupport/modules/playlistExecutor/src/ClientContext.h b/livesupport/modules/playlistExecutor/src/ClientContext.h index 5209483c3..91ed40bba 100644 --- a/livesupport/modules/playlistExecutor/src/ClientContext.h +++ b/livesupport/modules/playlistExecutor/src/ClientContext.h @@ -22,7 +22,7 @@ Author : $Author: maroy $ - Version : $Revision: 1.1 $ + Version : $Revision: 1.2 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/playlistExecutor/src/Attic/ClientContext.h,v $ ------------------------------------------------------------------------------*/ @@ -43,12 +43,13 @@ #include #include +#include "LiveSupport/Core/Ptr.h" #include "AdviseSink.h" namespace LiveSupport { namespace PlaylistExecutor { -using namespace LiveSupport; +using namespace LiveSupport::Core; /* ================================================================ constants */ @@ -60,12 +61,13 @@ using namespace LiveSupport; /* =============================================================== data types */ class ExampleErrorMessages; +class HelixPlayer; /** * A Helix client context. * * @author $Author: maroy $ - * @version $Revision: 1.1 $ + * @version $Revision: 1.2 $ */ class ClientContext : public IHXPreferences { @@ -75,6 +77,11 @@ class ClientContext : public IHXPreferences */ LONG32 lRefCount; + /** + * The HelixPlayer object this is the client context for, + */ + Ptr::Ref helixPlayer; + /** * The advise sink recieving event notifications. */ @@ -105,8 +112,10 @@ class ClientContext : public IHXPreferences /** * Constructor. + * + * @param helixPlayer the HelixPlayer this is a client context for. */ - ClientContext() throw (); + ClientContext(Ptr::Ref helixPlayer) throw (); /** * Destructor. diff --git a/livesupport/modules/playlistExecutor/src/HelixPlayer.cxx b/livesupport/modules/playlistExecutor/src/HelixPlayer.cxx index d1859d750..f5d38bdd1 100644 --- a/livesupport/modules/playlistExecutor/src/HelixPlayer.cxx +++ b/livesupport/modules/playlistExecutor/src/HelixPlayer.cxx @@ -22,7 +22,7 @@ Author : $Author: maroy $ - Version : $Revision: 1.5 $ + Version : $Revision: 1.6 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/playlistExecutor/src/Attic/HelixPlayer.cxx,v $ ------------------------------------------------------------------------------*/ @@ -158,7 +158,7 @@ HelixPlayer :: initialize(void) throw (std::exception) } // create and attach the client context - clientContext = new ClientContext(); + clientContext = new ClientContext(shared_from_this()); clientContext->AddRef(); IHXPreferences * preferences = 0; @@ -227,9 +227,10 @@ HelixPlayer :: deInitialize(void) throw () * Specify which file to play *----------------------------------------------------------------------------*/ void -HelixPlayer :: playThis(const std::string fileUrl) +HelixPlayer :: open(const std::string fileUrl) throw (std::invalid_argument) { + playlength = 0UL; // the only way to check if this is a valid URL is to see if the // source count increases for the player. UINT16 sourceCount = player->GetSourceCount(); @@ -242,6 +243,33 @@ HelixPlayer :: playThis(const std::string fileUrl) } +/*------------------------------------------------------------------------------ + * Get the length of the current audio clip. + *----------------------------------------------------------------------------*/ +Ptr::Ref +HelixPlayer :: getPlaylength(void) throw () +{ + Ptr::Ref length; + + // only bother if there is something to check for. + if (player->GetSourceCount() > 0) { + Ptr::Ref sleepT(new time_duration(microseconds(100))); + + // wait until the playlength is set to a sensible value + // by the advise sink. this may take a while + while (playlength == 0) { + TimeConversion::sleep(sleepT); + } + + unsigned long secs = playlength / 1000UL; + unsigned long millisecs = playlength - (secs * 1000UL); + length.reset(new time_duration(seconds(secs) + millisec(millisecs))); + } + + return length; +} + + /*------------------------------------------------------------------------------ * Start playing *----------------------------------------------------------------------------*/ diff --git a/livesupport/modules/playlistExecutor/src/HelixPlayer.h b/livesupport/modules/playlistExecutor/src/HelixPlayer.h index a64660caf..3fe5900bc 100644 --- a/livesupport/modules/playlistExecutor/src/HelixPlayer.h +++ b/livesupport/modules/playlistExecutor/src/HelixPlayer.h @@ -22,7 +22,7 @@ Author : $Author: maroy $ - Version : $Revision: 1.4 $ + Version : $Revision: 1.5 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/playlistExecutor/src/Attic/HelixPlayer.h,v $ ------------------------------------------------------------------------------*/ @@ -40,6 +40,7 @@ #include "configure.h" #endif +#include #include #include @@ -48,7 +49,6 @@ #include "LiveSupport/Core/Thread.h" #include "LiveSupport/PlaylistExecutor/AudioPlayerInterface.h" -#include "AdviseSink.h" #include "ErrorSink.h" #include "AuthenticationManager.h" #include "ClientContext.h" @@ -57,6 +57,8 @@ namespace LiveSupport { namespace PlaylistExecutor { +using namespace boost; + using namespace LiveSupport; using namespace LiveSupport::Core; @@ -89,10 +91,11 @@ using namespace LiveSupport::Core; * * * @author $Author: maroy $ - * @version $Revision: 1.4 $ + * @version $Revision: 1.5 $ */ class HelixPlayer : virtual public Configurable, - virtual public AudioPlayerInterface + virtual public AudioPlayerInterface, + public boost::enable_shared_from_this { private: /** @@ -140,6 +143,12 @@ class HelixPlayer : virtual public Configurable, */ std::string url; + /** + * The length of the currently playing audio clip, + * in milliseconds. + */ + unsigned long playlength; + /** * Flag to indicate if this object has been initialized. */ @@ -168,6 +177,7 @@ class HelixPlayer : virtual public Configurable, { playing = false; initialized = false; + playlength = 0UL; } /** @@ -226,14 +236,32 @@ 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(). * * @param fileUrl a URL to a file * @exception std::invalid_argument if the supplied fileUrl * seems to be invalid. + * @see #close * @see #start */ virtual void - playThis(const std::string fileUrl) throw (std::invalid_argument); + open(const std::string fileUrl) throw (std::invalid_argument); + + /** + * Close an audio source that was opened. + * + * @see #open + */ + virtual void + close(void) throw () + { + if (isPlaying()) { + stop(); + } + + // nothing else to do here, the Helix Player object does not + // have a close() function... + } /** * Start playing. @@ -266,6 +294,30 @@ class HelixPlayer : virtual public Configurable, */ virtual void stop(void) throw (std::logic_error); + + /** + * Set the length of the currenlty playing audio clip. + * This is called by AdviseSink only! + * + * @param playlength the length of the currently playing audio clip. + * in milliseconds + * @see AdviseSink#OnPosLength + */ + void + setPlaylength(unsigned long playlength) + { + this->playlength = playlength; + } + + /** + * Get the length of the currently opened audio clip. + * This function waits as long as necessary to get the length. + * + * @return the length of the currently playing audio clip, or 0, + * if nothing is openned. + */ + virtual Ptr::Ref + getPlaylength(void) throw (); }; diff --git a/livesupport/modules/playlistExecutor/src/HelixPlayerTest.cxx b/livesupport/modules/playlistExecutor/src/HelixPlayerTest.cxx index 003192dbe..6c02f59db 100644 --- a/livesupport/modules/playlistExecutor/src/HelixPlayerTest.cxx +++ b/livesupport/modules/playlistExecutor/src/HelixPlayerTest.cxx @@ -22,7 +22,7 @@ Author : $Author: maroy $ - Version : $Revision: 1.5 $ + Version : $Revision: 1.6 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/playlistExecutor/src/Attic/HelixPlayerTest.cxx,v $ ------------------------------------------------------------------------------*/ @@ -119,6 +119,26 @@ HelixPlayerTest :: firstTest(void) } +/*------------------------------------------------------------------------------ + * Check the length of an audio file + *----------------------------------------------------------------------------*/ +void +HelixPlayerTest :: playlengthTest(void) + throw (CPPUNIT_NS::Exception) +{ + Ptr::Ref sleepT(new time_duration(microseconds(10))); + + helixPlayer->initialize(); + helixPlayer->open("file:var/test.mp3"); + CPPUNIT_ASSERT(!helixPlayer->isPlaying()); + Ptr::Ref playlength = helixPlayer->getPlaylength(); + CPPUNIT_ASSERT(playlength->seconds() == 14); + CPPUNIT_ASSERT(playlength->fractional_seconds() == 785000); + helixPlayer->close(); + helixPlayer->deInitialize(); +} + + /*------------------------------------------------------------------------------ * Play something simple *----------------------------------------------------------------------------*/ @@ -129,7 +149,7 @@ HelixPlayerTest :: simplePlayTest(void) Ptr::Ref sleepT(new time_duration(microseconds(10))); helixPlayer->initialize(); - helixPlayer->playThis("file:var/test.mp3"); + helixPlayer->open("file:var/test.mp3"); CPPUNIT_ASSERT(!helixPlayer->isPlaying()); helixPlayer->start(); CPPUNIT_ASSERT(helixPlayer->isPlaying()); @@ -137,6 +157,7 @@ HelixPlayerTest :: simplePlayTest(void) TimeConversion::sleep(sleepT); } CPPUNIT_ASSERT(!helixPlayer->isPlaying()); + helixPlayer->close(); helixPlayer->deInitialize(); } @@ -172,7 +193,7 @@ HelixPlayerTest :: checkErrorConditions(void) gotException = false; try { - helixPlayer->playThis("totally/bad/URL"); + helixPlayer->open("totally/bad/URL"); } catch (std::invalid_argument &e) { gotException = true; } @@ -201,7 +222,7 @@ HelixPlayerTest :: smilTest(void) helixPlayer->initialize(); - helixPlayer->playThis("file:var/simpleSmil.smil"); + helixPlayer->open("file:var/simpleSmil.smil"); CPPUNIT_ASSERT(!helixPlayer->isPlaying()); helixPlayer->start(); CPPUNIT_ASSERT(helixPlayer->isPlaying()); @@ -209,6 +230,9 @@ HelixPlayerTest :: smilTest(void) TimeConversion::sleep(sleepT); } CPPUNIT_ASSERT(!helixPlayer->isPlaying()); + + helixPlayer->close(); + helixPlayer->deInitialize(); } @@ -222,7 +246,7 @@ HelixPlayerTest :: playFile(const std::string & fileName) { Ptr::Ref sleepT(new time_duration(microseconds(10))); - helixPlayer->playThis(fileName.c_str()); + helixPlayer->open(fileName.c_str()); CPPUNIT_ASSERT(!helixPlayer->isPlaying()); helixPlayer->start(); CPPUNIT_ASSERT(helixPlayer->isPlaying()); @@ -230,6 +254,7 @@ HelixPlayerTest :: playFile(const std::string & fileName) TimeConversion::sleep(sleepT); } CPPUNIT_ASSERT(!helixPlayer->isPlaying()); + helixPlayer->close(); } @@ -307,7 +332,7 @@ HelixPlayerTest :: smilSoundAnimationTest(void) /* TODO: there is a bug with sound level animation, it causes a segfault see https://bugs.helixcommunity.org/show_bug.cgi?id=3310 */ - helixPlayer->playThis("file:var/animateSound.smil"); + helixPlayer->open("file:var/animateSound.smil"); CPPUNIT_ASSERT(!helixPlayer->isPlaying()); helixPlayer->start(); CPPUNIT_ASSERT(helixPlayer->isPlaying()); @@ -315,6 +340,7 @@ HelixPlayerTest :: smilSoundAnimationTest(void) 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 25e66384f..019f129e4 100644 --- a/livesupport/modules/playlistExecutor/src/HelixPlayerTest.h +++ b/livesupport/modules/playlistExecutor/src/HelixPlayerTest.h @@ -22,7 +22,7 @@ Author : $Author: maroy $ - Version : $Revision: 1.5 $ + Version : $Revision: 1.6 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/playlistExecutor/src/Attic/HelixPlayerTest.h,v $ ------------------------------------------------------------------------------*/ @@ -58,13 +58,14 @@ namespace PlaylistExecutor { * Unit test for the HelixPlayer class. * * @author $Author: maroy $ - * @version $Revision: 1.5 $ + * @version $Revision: 1.6 $ * @see HelixPlayer */ class HelixPlayerTest : public CPPUNIT_NS::TestFixture { CPPUNIT_TEST_SUITE(HelixPlayerTest); CPPUNIT_TEST(firstTest); + CPPUNIT_TEST(playlengthTest); CPPUNIT_TEST(simplePlayTest); CPPUNIT_TEST(checkErrorConditions); CPPUNIT_TEST(smilTest); @@ -73,7 +74,7 @@ class HelixPlayerTest : public CPPUNIT_NS::TestFixture CPPUNIT_TEST(smilParallelTest2); CPPUNIT_TEST(smilParallelTest3); CPPUNIT_TEST(smilParallelTest4); -// CPPUNIT_TEST(smilSoundAnimationTest); + CPPUNIT_TEST(smilSoundAnimationTest); CPPUNIT_TEST_SUITE_END(); private: @@ -104,6 +105,14 @@ class HelixPlayerTest : public CPPUNIT_NS::TestFixture void firstTest(void) throw (CPPUNIT_NS::Exception); + /** + * Check the length of an audio file + * + * @exception CPPUNIT_NS::Exception on test failures. + */ + void + playlengthTest(void) throw (CPPUNIT_NS::Exception); + /** * Play something simple. *