From 268c5a727b274916e0a0cc4bd61c3ed892a0b224 Mon Sep 17 00:00:00 2001 From: Andre Fischer Date: Wed, 4 Mar 2009 13:41:44 +0000 Subject: #i48179# Introduced EffectRewinder class that replays main sequence effects on current or previous slide. --- slideshow/source/engine/slideshowimpl.cxx | 262 +++++++++++++++++++++++++----- 1 file changed, 218 insertions(+), 44 deletions(-) (limited to 'slideshow/source/engine/slideshowimpl.cxx') diff --git a/slideshow/source/engine/slideshowimpl.cxx b/slideshow/source/engine/slideshowimpl.cxx index 18c834e4dfb0..162b3cb8dc2c 100644 --- a/slideshow/source/engine/slideshowimpl.cxx +++ b/slideshow/source/engine/slideshowimpl.cxx @@ -92,6 +92,7 @@ #include "slidebitmap.hxx" #include "rehearsetimingsactivity.hxx" #include "waitsymbol.hxx" +#include "effectrewinder.hxx" #include #include @@ -193,7 +194,7 @@ public: This method notifies the end of the third phase. */ - void notifySlideEnded(); + void notifySlideEnded (const bool bReverse); /** Notification from eventmultiplexer that a hyperlink has been clicked. @@ -208,6 +209,7 @@ public: private: // XSlideShow: virtual sal_Bool SAL_CALL nextEffect() throw (uno::RuntimeException); + virtual sal_Bool SAL_CALL previousEffect() throw (uno::RuntimeException); virtual sal_Bool SAL_CALL startShapeActivity( uno::Reference const& xShape ) throw (uno::RuntimeException); @@ -258,6 +260,12 @@ private: virtual bool requestCursor( sal_Int16 nCursorShape ); virtual void resetCursor(); + /** This is somewhat similar to displaySlide when called for the current + slide. It has been simplified to take advantage of that no slide + change takes place. Furthermore it does not show the slide + transition. + */ + void redisplayCurrentSlide (void); protected: // WeakComponentImplHelperBase @@ -313,12 +321,32 @@ private: const SlideSharedPtr& rEnteringSlide, const EventSharedPtr& rTransitionEndEvent ); - /// Display/hide wait symbol on all views - void setWaitState( bool bOn ); + /** Request/release the wait symbol. The wait symbol is displayed when + there are more requests then releases. Locking the wait symbol + helps to avoid intermediate repaints. + + Do not call this method directly. Use WaitSymbolLock instead. + */ + void requestWaitSymbol (void); + void releaseWaitSymbol (void); + + class WaitSymbolLock {public: + WaitSymbolLock(SlideShowImpl& rSlideShowImpl) : mrSlideShowImpl(rSlideShowImpl) + { mrSlideShowImpl.requestWaitSymbol(); } + ~WaitSymbolLock(void) + { mrSlideShowImpl.releaseWaitSymbol(); } + private: SlideShowImpl& mrSlideShowImpl; + }; + /// Filter requested cursor shape against hard slideshow cursors (wait, etc.) sal_Int16 calcActiveCursor( sal_Int16 nCursorShape ) const; + /** This method is called asynchronously to finish the rewinding of an + effect to the previous slide that was initiated earlier. + */ + void rewindEffectToPreviousSlide (void); + /// all registered views UnoViewContainer maViewContainer; @@ -365,7 +393,7 @@ private: sal_Int16 mnCurrentCursor; - bool mbWaitState; + sal_Int32 mnWaitSymbolRequestCount; bool mbAutomaticAdvancementMode; bool mbImageAnimationsAllowed; bool mbNoSlideTransitions; @@ -374,6 +402,8 @@ private: bool mbShowPaused; bool mbSlideShowIdle; bool mbDisableAnimationZOrder; + + EffectRewinder maEffectRewinder; }; @@ -465,7 +495,7 @@ SlideShowImpl::SlideShowImpl( mxPrefetchSlide(), mxPrefetchAnimationNode(), mnCurrentCursor(awt::SystemPointer::ARROW), - mbWaitState(false), + mnWaitSymbolRequestCount(0), mbAutomaticAdvancementMode(false), mbImageAnimationsAllowed( true ), mbNoSlideTransitions( false ), @@ -473,7 +503,8 @@ SlideShowImpl::SlideShowImpl( mbForceManualAdvance( false ), mbShowPaused( false ), mbSlideShowIdle( true ), - mbDisableAnimationZOrder( false ) + mbDisableAnimationZOrder( false ), + maEffectRewinder(maEventMultiplexer, maEventQueue, maUserEventQueue) { // keep care not constructing any UNO references to this inside ctor, // shift that code to create()! @@ -507,6 +538,8 @@ void SlideShowImpl::disposing() { osl::MutexGuard const guard( m_aMutex ); + maEffectRewinder.Dispose(); + // stop slide transition sound, if any: stopSlideTransitionSound(); @@ -607,7 +640,7 @@ ActivitySharedPtr SlideShowImpl::createSlideTransition( const uno::Reference< drawing::XDrawPage >& xDrawPage, const SlideSharedPtr& rLeavingSlide, const SlideSharedPtr& rEnteringSlide, - const EventSharedPtr& rTransitionEndEvent ) + const EventSharedPtr& rTransitionEndEvent) { ENSURE_OR_THROW( !maViewContainer.empty(), "createSlideTransition(): No views" ); @@ -778,20 +811,43 @@ SlideSharedPtr SlideShowImpl::makeSlide( return pSlide; } -void SlideShowImpl::setWaitState( bool bOn ) +void SlideShowImpl::requestWaitSymbol (void) { - mbWaitState = bOn; - if( !mpWaitSymbol ) // fallback to cursor - requestCursor(awt::SystemPointer::WAIT); - else if( mbWaitState ) - mpWaitSymbol->show(); - else - mpWaitSymbol->hide(); + ++mnWaitSymbolRequestCount; + OSL_ASSERT(mnWaitSymbolRequestCount>0); + + if (mnWaitSymbolRequestCount == 1) + { + if( !mpWaitSymbol ) + { + // fall back to cursor + requestCursor(calcActiveCursor(mnCurrentCursor)); + } + else + mpWaitSymbol->show(); + } +} + +void SlideShowImpl::releaseWaitSymbol (void) +{ + --mnWaitSymbolRequestCount; + OSL_ASSERT(mnWaitSymbolRequestCount>=0); + + if (mnWaitSymbolRequestCount == 0) + { + if( !mpWaitSymbol ) + { + // fall back to cursor + requestCursor(calcActiveCursor(mnCurrentCursor)); + } + else + mpWaitSymbol->hide(); + } } sal_Int16 SlideShowImpl::calcActiveCursor( sal_Int16 nCursorShape ) const { - if( mbWaitState && !mpWaitSymbol ) // enforce wait cursor + if( mnWaitSymbolRequestCount>0 && !mpWaitSymbol ) // enforce wait cursor nCursorShape = awt::SystemPointer::WAIT; else if( !mbMouseVisible ) // enforce INVISIBLE nCursorShape = awt::SystemPointer::INVISIBLE; @@ -835,10 +891,19 @@ void SlideShowImpl::stopShow() } } -struct SlideShowImpl::PrefetchPropertiesFunc + + +class SlideShowImpl::PrefetchPropertiesFunc { - SlideShowImpl *const that; - PrefetchPropertiesFunc( SlideShowImpl * that_ ) : that(that_) {} +public: + PrefetchPropertiesFunc( SlideShowImpl * that_, + bool& rbSkipAllMainSequenceEffects, + bool& rbSkipSlideTransition) + : mpSlideShowImpl(that_), + mrbSkipAllMainSequenceEffects(rbSkipAllMainSequenceEffects), + mrbSkipSlideTransition(rbSkipSlideTransition) + {} + void operator()( beans::PropertyValue const& rProperty ) const { if (rProperty.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Prefetch") )) @@ -846,16 +911,30 @@ struct SlideShowImpl::PrefetchPropertiesFunc uno::Sequence seq; if ((rProperty.Value >>= seq) && seq.getLength() == 2) { - seq[0] >>= that->mxPrefetchSlide; - seq[1] >>= that->mxPrefetchAnimationNode; + seq[0] >>= mpSlideShowImpl->mxPrefetchSlide; + seq[1] >>= mpSlideShowImpl->mxPrefetchAnimationNode; } } + else if (rProperty.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM("SkipAllMainSequenceEffects") )) + { + rProperty.Value >>= mrbSkipAllMainSequenceEffects; + } + else if (rProperty.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM("SkipSlideTransition") )) + { + rProperty.Value >>= mrbSkipSlideTransition; + } else { OSL_ENSURE( false, rtl::OUStringToOString( rProperty.Name, RTL_TEXTENCODING_UTF8 ).getStr() ); } } +private: + SlideShowImpl *const mpSlideShowImpl; + bool& mrbSkipAllMainSequenceEffects; + bool& mrbSkipSlideTransition; }; void SlideShowImpl::displaySlide( @@ -869,6 +948,8 @@ void SlideShowImpl::displaySlide( if (isDisposed()) return; + maEffectRewinder.SetRootAnimationNode(xRootNode); + // precondition: must only be called from the main thread! DBG_TESTSOLARMUTEX(); @@ -881,9 +962,11 @@ void SlideShowImpl::displaySlide( // shape animations (drawing layer and // GIF) will not be stopped. + bool bSkipAllMainSequenceEffects (false); + bool bSkipSlideTransition (false); std::for_each( rProperties.getConstArray(), rProperties.getConstArray() + rProperties.getLength(), - PrefetchPropertiesFunc(this) ); + PrefetchPropertiesFunc(this, bSkipAllMainSequenceEffects, bSkipSlideTransition) ); OSL_ENSURE( !maViewContainer.empty(), "### no views!" ); if (maViewContainer.empty()) @@ -891,9 +974,7 @@ void SlideShowImpl::displaySlide( // this here might take some time { - comphelper::ScopeGuard const scopeGuard( - boost::bind( &SlideShowImpl::setWaitState, this, false ) ); - setWaitState(true); + WaitSymbolLock aLock (*this); mpPreviousSlide = mpCurrentSlide; mpCurrentSlide.reset(); @@ -935,15 +1016,25 @@ void SlideShowImpl::displaySlide( // create slide transition, and add proper end event // (which then starts the slide effects // via CURRENT_SLIDE.show()) - ActivitySharedPtr const pSlideChangeActivity( - createSlideTransition( mpCurrentSlide->getXDrawPage(), - mpPreviousSlide, - mpCurrentSlide, - makeEvent( - boost::bind( - &SlideShowImpl::notifySlideTransitionEnded, - this, - false )))); + ActivitySharedPtr pSlideChangeActivity ( + createSlideTransition( + mpCurrentSlide->getXDrawPage(), + mpPreviousSlide, + mpCurrentSlide, + makeEvent( + boost::bind( + &SlideShowImpl::notifySlideTransitionEnded, + this, + false )))); + + if (bSkipSlideTransition) + { + // The transition activity was created for the side effects + // (like sound transitions). Because we want to skip the + // acutual transition animation we do not need the activity + // anymore. + pSlideChangeActivity.reset(); + } if (pSlideChangeActivity) { @@ -967,6 +1058,43 @@ void SlideShowImpl::displaySlide( maEventMultiplexer.notifySlideTransitionStarted(); maListenerContainer.forEach( boost::mem_fn( &presentation::XSlideShowListener::slideTransitionStarted ) ); + + // We are currently rewinding an effect. This lead us from the next + // slide to this one. To complete this we have to play back all main + // sequence effects on this slide. + if (bSkipAllMainSequenceEffects) + maEffectRewinder.SkipAllMainSequenceEffects(); +} + +void SlideShowImpl::redisplayCurrentSlide (void) +{ + osl::MutexGuard const guard( m_aMutex ); + + if (isDisposed()) + return; + + // precondition: must only be called from the main thread! + DBG_TESTSOLARMUTEX(); + stopShow(); + bool bSkipAllMainSequenceEffects (false); + bool bSkipSlideTransition (true); + + OSL_ENSURE( !maViewContainer.empty(), "### no views!" ); + if (maViewContainer.empty()) + return; + + // No transition effect on this slide - schedule slide + // effect start event right away. + maEventQueue.addEvent( + makeEvent( + boost::bind( + &SlideShowImpl::notifySlideTransitionEnded, + this, + true ))); + + maEventMultiplexer.notifySlideTransitionStarted(); + maListenerContainer.forEach( + boost::mem_fn( &presentation::XSlideShowListener::slideTransitionStarted ) ); } sal_Bool SlideShowImpl::nextEffect() throw (uno::RuntimeException) @@ -985,6 +1113,50 @@ sal_Bool SlideShowImpl::nextEffect() throw (uno::RuntimeException) return maEventMultiplexer.notifyNextEffect(); } + +sal_Bool SlideShowImpl::previousEffect() throw (uno::RuntimeException) +{ + osl::MutexGuard const guard( m_aMutex ); + + if (isDisposed()) + return false; + + // precondition: must only be called from the main thread! + DBG_TESTSOLARMUTEX(); + + if (mbShowPaused) + return true; + else + { + return maEffectRewinder.Rewind( + maScreenUpdater.createLock(false), + ::boost::bind(&SlideShowImpl::redisplayCurrentSlide, this), + ::boost::bind(&SlideShowImpl::rewindEffectToPreviousSlide, this)); + } +} + +void SlideShowImpl::rewindEffectToPreviousSlide (void) +{ + // Show the wait symbol now and prevent it from showing temporary slide + // content while effects are played back. + WaitSymbolLock aLock (*this); + + // A previous call to EffectRewinder::Rewind could not rewind the current + // effect because there are no effects on the current slide or none has + // yet been displayed. Go to the previous slide. + notifySlideEnded(true); + + // Process pending events once more in order to have the following + // screen update show the last effect. Not sure whether this should be + // necessary. + maEventQueue.forceEmpty(); + + // We have to call the screen updater before the wait symbol is turned + // off. Otherwise the wait symbol would force the display of an + // intermediate state of the slide (before the effects are replayed.) + maScreenUpdater.commitUpdates(); +} + sal_Bool SlideShowImpl::startShapeActivity( uno::Reference const& /*xShape*/ ) throw (uno::RuntimeException) @@ -1658,7 +1830,7 @@ void SlideShowImpl::notifySlideAnimationsEnded() // schedule a slide end event, with automatic mode's // delay aNotificationEvents = makeInterruptableDelay( - boost::bind( &SlideShowImpl::notifySlideEnded, this ), + boost::bind( &SlideShowImpl::notifySlideEnded, this, false ), maEventMultiplexer.getAutomaticTimeout() ); } else @@ -1683,7 +1855,7 @@ void SlideShowImpl::notifySlideAnimationsEnded() bHasAutomaticNextSlide ) { aNotificationEvents = makeInterruptableDelay( - boost::bind( &SlideShowImpl::notifySlideEnded, this ), + boost::bind( &SlideShowImpl::notifySlideEnded, this, false ), nAutomaticNextSlideTimeout); // TODO(F2): Provide a mechanism to let the user override @@ -1700,7 +1872,7 @@ void SlideShowImpl::notifySlideAnimationsEnded() // timeout involved. aNotificationEvents.mpImmediateEvent = makeEvent( boost::bind( - &SlideShowImpl::notifySlideEnded, this ) ); + &SlideShowImpl::notifySlideEnded, this, false ) ); } } @@ -1721,9 +1893,7 @@ void SlideShowImpl::notifySlideAnimationsEnded() // change setup time a lot). Show the wait cursor, this // indeed might take some seconds. { - comphelper::ScopeGuard const scopeGuard( - boost::bind( &SlideShowImpl::setWaitState, this, false ) ); - setWaitState(true); + WaitSymbolLock aLock (*this); if (! matches( mpPrefetchSlide, mxPrefetchSlide, mxPrefetchAnimationNode )) @@ -1745,13 +1915,13 @@ void SlideShowImpl::notifySlideAnimationsEnded() boost::mem_fn( &presentation::XSlideShowListener::slideAnimationsEnded ) ); } -void SlideShowImpl::notifySlideEnded() +void SlideShowImpl::notifySlideEnded (const bool bReverse) { osl::MutexGuard const guard( m_aMutex ); OSL_ENSURE( !isDisposed(), "### already disposed!" ); - if (mpRehearseTimingsActivity) + if (mpRehearseTimingsActivity && !bReverse) { const double time = mpRehearseTimingsActivity->stop(); if (mpRehearseTimingsActivity->hasBeenClicked()) @@ -1772,7 +1942,8 @@ void SlideShowImpl::notifySlideEnded() } } - maEventMultiplexer.notifySlideEndEvent(); + if (bReverse) + maEventMultiplexer.notifySlideEndEvent(); stopShow(); // MUST call that: results in // maUserEventQueue.clear(). What's more, @@ -1784,7 +1955,10 @@ void SlideShowImpl::notifySlideEnded() // GIF) will not be stopped. maListenerContainer.forEach( - boost::mem_fn( &presentation::XSlideShowListener::slideEnded ) ); + boost::bind( + &presentation::XSlideShowListener::slideEnded, + _1, + bReverse) ); } bool SlideShowImpl::notifyHyperLinkClicked( rtl::OUString const& hyperLink ) -- cgit From 6ff3e037e87b5ca49f177eb1899f0c6715427782 Mon Sep 17 00:00:00 2001 From: Thorsten Behrens Date: Fri, 6 Mar 2009 09:08:49 +0000 Subject: #i10000# CodingStandards: aligned EffectRewinder class to module conventions; WaE: removed two unused vars --- slideshow/source/engine/slideshowimpl.cxx | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'slideshow/source/engine/slideshowimpl.cxx') diff --git a/slideshow/source/engine/slideshowimpl.cxx b/slideshow/source/engine/slideshowimpl.cxx index 162b3cb8dc2c..919cd478c160 100644 --- a/slideshow/source/engine/slideshowimpl.cxx +++ b/slideshow/source/engine/slideshowimpl.cxx @@ -538,7 +538,7 @@ void SlideShowImpl::disposing() { osl::MutexGuard const guard( m_aMutex ); - maEffectRewinder.Dispose(); + maEffectRewinder.dispose(); // stop slide transition sound, if any: stopSlideTransitionSound(); @@ -948,7 +948,7 @@ void SlideShowImpl::displaySlide( if (isDisposed()) return; - maEffectRewinder.SetRootAnimationNode(xRootNode); + maEffectRewinder.setRootAnimationNode(xRootNode); // precondition: must only be called from the main thread! DBG_TESTSOLARMUTEX(); @@ -1063,7 +1063,7 @@ void SlideShowImpl::displaySlide( // slide to this one. To complete this we have to play back all main // sequence effects on this slide. if (bSkipAllMainSequenceEffects) - maEffectRewinder.SkipAllMainSequenceEffects(); + maEffectRewinder.skipAllMainSequenceEffects(); } void SlideShowImpl::redisplayCurrentSlide (void) @@ -1076,8 +1076,6 @@ void SlideShowImpl::redisplayCurrentSlide (void) // precondition: must only be called from the main thread! DBG_TESTSOLARMUTEX(); stopShow(); - bool bSkipAllMainSequenceEffects (false); - bool bSkipSlideTransition (true); OSL_ENSURE( !maViewContainer.empty(), "### no views!" ); if (maViewContainer.empty()) @@ -1128,7 +1126,7 @@ sal_Bool SlideShowImpl::previousEffect() throw (uno::RuntimeException) return true; else { - return maEffectRewinder.Rewind( + return maEffectRewinder.rewind( maScreenUpdater.createLock(false), ::boost::bind(&SlideShowImpl::redisplayCurrentSlide, this), ::boost::bind(&SlideShowImpl::rewindEffectToPreviousSlide, this)); -- cgit From 3444422cc1fd774961c43d5699a15f4e4b13d6d1 Mon Sep 17 00:00:00 2001 From: Andre Fischer Date: Tue, 24 Mar 2009 13:53:29 +0000 Subject: #i98806# Added IsSoundEnabled property to mute sound in some slide show views. --- slideshow/source/engine/slideshowimpl.cxx | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'slideshow/source/engine/slideshowimpl.cxx') diff --git a/slideshow/source/engine/slideshowimpl.cxx b/slideshow/source/engine/slideshowimpl.cxx index 919cd478c160..2658f2a490eb 100644 --- a/slideshow/source/engine/slideshowimpl.cxx +++ b/slideshow/source/engine/slideshowimpl.cxx @@ -1451,6 +1451,34 @@ sal_Bool SlideShowImpl::setProperty( beans::PropertyValue const& rProperty ) return (rProperty.Value >>= mbNoSlideTransitions); } + if (rProperty.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("IsSoundEnabled"))) + { + uno::Sequence aValues; + uno::Reference xView; + sal_Bool bValue; + if ((rProperty.Value >>= aValues) + && aValues.getLength()==2 + && (aValues[0] >>= xView) + && (aValues[1] >>= bValue)) + { + // Look up the view. + for (UnoViewVector::const_iterator + iView (maViewContainer.begin()), + iEnd (maViewContainer.end()); + iView!=iEnd; + ++iView) + { + if (*iView && (*iView)->getUnoView()==xView) + { + // Store the flag at the view so that media shapes have + // access to it. + (*iView)->setIsSoundEnabled(bValue); + return true; + } + } + } + } + return false; } -- cgit From 789327979618b8e6d6cb1577167e1999010dc23c Mon Sep 17 00:00:00 2001 From: Andre Fischer Date: Wed, 1 Apr 2009 11:54:54 +0000 Subject: #i48719# Fixed compilation problem. --- slideshow/source/engine/slideshowimpl.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'slideshow/source/engine/slideshowimpl.cxx') diff --git a/slideshow/source/engine/slideshowimpl.cxx b/slideshow/source/engine/slideshowimpl.cxx index a23c4b5f35d9..243f378d7223 100644 --- a/slideshow/source/engine/slideshowimpl.cxx +++ b/slideshow/source/engine/slideshowimpl.cxx @@ -1464,7 +1464,7 @@ sal_Bool SlideShowImpl::setProperty( beans::PropertyValue const& rProperty ) { uno::Sequence aValues; uno::Reference xView; - sal_Bool bValue; + sal_Bool bValue (false); if ((rProperty.Value >>= aValues) && aValues.getLength()==2 && (aValues[0] >>= xView) -- cgit From e8c1911592680b712cd989205e70918783bf4566 Mon Sep 17 00:00:00 2001 From: Andre Fischer Date: Tue, 21 Apr 2009 08:27:57 +0000 Subject: #i96540# Hold timer even for single activities. --- slideshow/source/engine/slideshowimpl.cxx | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'slideshow/source/engine/slideshowimpl.cxx') diff --git a/slideshow/source/engine/slideshowimpl.cxx b/slideshow/source/engine/slideshowimpl.cxx index 243f378d7223..8fd1cb07ca48 100644 --- a/slideshow/source/engine/slideshowimpl.cxx +++ b/slideshow/source/engine/slideshowimpl.cxx @@ -1669,19 +1669,17 @@ sal_Bool SlideShowImpl::update( double & nNextTimeout ) // TODO(F2): re-evaluate whether that timer lagging makes // sense. - // hold timer, while processing the queues (ensures - // same time for all activities and events) + // hold timer, while processing the queues: + // 1. when there is more than one active activity this ensures the + // same time for all activities and events + // 2. processing of events may lead to creation of further events + // that have zero delay. While the timer is stopped these events + // are processed in the same run. { comphelper::ScopeGuard scopeGuard( boost::bind( &canvas::tools::ElapsedTime::releaseTimer, boost::cref(mpPresTimer) ) ); - - // no need to hold timer for only one active animation - - // it's only meant to keep multiple ones in sync - if( maActivitiesQueue.size() > 1 ) - mpPresTimer->holdTimer(); - else - scopeGuard.dismiss(); // we're not holding the timer + mpPresTimer->holdTimer(); // process queues maEventQueue.process(); -- cgit From aa02f1da390cb9b1225de978f8e2965c34e3a45f Mon Sep 17 00:00:00 2001 From: Andre Fischer Date: Mon, 27 Apr 2009 11:25:13 +0000 Subject: #i98792# Synchronize frame rate during animations. --- slideshow/source/engine/slideshowimpl.cxx | 130 +++++++++++++++++++++++++++++- 1 file changed, 128 insertions(+), 2 deletions(-) (limited to 'slideshow/source/engine/slideshowimpl.cxx') diff --git a/slideshow/source/engine/slideshowimpl.cxx b/slideshow/source/engine/slideshowimpl.cxx index 8fd1cb07ca48..5ace44acda65 100644 --- a/slideshow/source/engine/slideshowimpl.cxx +++ b/slideshow/source/engine/slideshowimpl.cxx @@ -110,6 +110,65 @@ using namespace ::slideshow::internal; namespace { +/** During animations the update() method tells its caller to call it as + soon as possible. This gives us more time to render the next frame and + still maintain a steady frame rate. This class is responsible for + synchronizing the display of new frames and thus keeping the frame rate + steady. +*/ +class FrameSynchronization +{ +public: + /** Create new object with a predefined duration between two frames. + @param nFrameDuration + The preferred duration between the display of two frames in + seconds. + */ + FrameSynchronization (const double nFrameDuration); + + /** Set the current time as the time at which the current frame is + displayed. From this the target time of the next frame is derived. + */ + void MarkCurrentFrame (void); + + /** When there is time left until the next frame is due then wait. + Otherwise return without delay. + */ + void Synchronize (void); + + /** Activate frame synchronization when an animation is active and + frames are to be displayed in a steady rate. While active + Synchronize() will wait until the frame duration time has passed. + */ + void Activate (void); + + /** Deactivate frame sychronization when no animation is active and the + time between frames depends on user actions and other external + sources. While deactivated Synchronize() will return without delay. + */ + void Deactivate (void); + +private: + /** The timer that is used for synchronization is independent from the + one used by SlideShowImpl: it is not paused or modified by + animations. + */ + canvas::tools::ElapsedTime maTimer; + /** Time between the display of frames. Enforced only when mbIsActive + is . + */ + const double mnFrameDuration; + /** Time (of maTimer) when the next frame shall be displayed. + Synchronize() will wait until this time. + */ + double mnNextFrameTargetTime; + /** Synchronize() will wait only when this flag is . Otherwise + it returns immediately. + */ + bool mbIsActive; +}; + + /****************************************************************************** SlideShowImpl @@ -407,6 +466,7 @@ private: bool mbDisableAnimationZOrder; EffectRewinder maEffectRewinder; + FrameSynchronization maFrameSynchronization; }; @@ -507,7 +567,9 @@ SlideShowImpl::SlideShowImpl( mbShowPaused( false ), mbSlideShowIdle( true ), mbDisableAnimationZOrder( false ), - maEffectRewinder(maEventMultiplexer, maEventQueue, maUserEventQueue) + maEffectRewinder(maEventMultiplexer, maEventQueue, maUserEventQueue), + maFrameSynchronization(1.0 / FrameRate::PreferredFramesPerSecond) + { // keep care not constructing any UNO references to this inside ctor, // shift that code to create()! @@ -1686,6 +1748,7 @@ sal_Bool SlideShowImpl::update( double & nNextTimeout ) maActivitiesQueue.process(); // commit frame to screen + maFrameSynchronization.Synchronize(); maScreenUpdater.commitUpdates(); // TODO(Q3): remove need to call dequeued() from @@ -1729,7 +1792,13 @@ sal_Bool SlideShowImpl::update( double & nNextTimeout ) { // Activity queue is not empty. Tell caller that we would // like to render another frame. - nNextTimeout = 1.0 / FrameRate::PreferredFramesPerSecond; + + // Return a zero time-out to signal our caller to call us + // back as soon as possible. The actual timing, waiting the + // appropriate amount of time between frames, is then done + // by the maFrameSynchronization object. + nNextTimeout = 0; + maFrameSynchronization.Activate(); } else { @@ -1743,6 +1812,10 @@ sal_Bool SlideShowImpl::update( double & nNextTimeout ) // ensure positive value: nNextTimeout = std::max( 0.0, maEventQueue.nextTimeout() ); + + // There is no active animation so the frame rate does not + // need to be synchronized. + maFrameSynchronization.Deactivate(); } mbSlideShowIdle = false; @@ -2038,6 +2111,59 @@ bool SlideShowImpl::handleAnimationEvent( const AnimationNodeSharedPtr& rNode ) return true; } + +//===== FrameSynchronization ================================================== + +FrameSynchronization::FrameSynchronization (const double nFrameDuration) + : maTimer(), + mnFrameDuration(nFrameDuration), + mnNextFrameTargetTime(0), + mbIsActive(false) +{ + MarkCurrentFrame(); +} + + + + +void FrameSynchronization::MarkCurrentFrame (void) +{ + mnNextFrameTargetTime = maTimer.getElapsedTime() + mnFrameDuration; +} + + + + +void FrameSynchronization::Synchronize (void) +{ + if (mbIsActive) + { + // Do busy waiting for now. + while (maTimer.getElapsedTime() < mnNextFrameTargetTime) + ; + } + + MarkCurrentFrame(); +} + + + + +void FrameSynchronization::Activate (void) +{ + mbIsActive = true; +} + + + + +void FrameSynchronization::Deactivate (void) +{ + mbIsActive = false; +} + + + } // anon namespace namespace sdecl = comphelper::service_decl; -- cgit From 69a4a545a556bd189736b3e510d4b4b07ae8cb6e Mon Sep 17 00:00:00 2001 From: Andre Fischer Date: Mon, 27 Apr 2009 11:42:05 +0000 Subject: #i48179# Debug: added descriptive strings to events. --- slideshow/source/engine/slideshowimpl.cxx | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'slideshow/source/engine/slideshowimpl.cxx') diff --git a/slideshow/source/engine/slideshowimpl.cxx b/slideshow/source/engine/slideshowimpl.cxx index 5ace44acda65..1ab20f7f294e 100644 --- a/slideshow/source/engine/slideshowimpl.cxx +++ b/slideshow/source/engine/slideshowimpl.cxx @@ -504,7 +504,8 @@ struct SlideShowImpl::SeparateListenerImpl : public EventHandler, // in recursion. mrEventQueue.addEvent( makeEvent( boost::bind( &SlideShowImpl::notifySlideAnimationsEnded, - boost::ref(mrShow) ))); + boost::ref(mrShow) ), + "SlideShowImpl::notifySlideAnimationsEnded")); return true; } @@ -831,7 +832,8 @@ ActivitySharedPtr SlideShowImpl::createSlideTransition( &::slideshow::internal::Animation::prefetch, pTransition, AnimatableShapeSharedPtr(), - ShapeAttributeLayerSharedPtr()))); + ShapeAttributeLayerSharedPtr()), + "Animation::prefetch")); return ActivitySharedPtr( ActivitiesFactory::createSimpleActivity( @@ -1096,7 +1098,8 @@ void SlideShowImpl::displaySlide( boost::bind( &SlideShowImpl::notifySlideTransitionEnded, this, - false )))); + false ), + "SlideShowImpl::notifySlideTransitionEnded"))); if (bSkipSlideTransition) { @@ -1121,7 +1124,8 @@ void SlideShowImpl::displaySlide( boost::bind( &SlideShowImpl::notifySlideTransitionEnded, this, - true ))); + true ), + "SlideShowImpl::notifySlideTransitionEnded")); } } } // finally @@ -1159,7 +1163,8 @@ void SlideShowImpl::redisplayCurrentSlide (void) boost::bind( &SlideShowImpl::notifySlideTransitionEnded, this, - true ))); + true ), + "SlideShowImpl::notifySlideTransitionEnded")); maEventMultiplexer.notifySlideTransitionStarted(); maListenerContainer.forEach( @@ -1777,6 +1782,7 @@ sal_Bool SlideShowImpl::update( double & nNextTimeout ) maActivitiesQueue.processDequeued(); // commit frame to screen + maFrameSynchronization.Synchronize(); maScreenUpdater.commitUpdates(); } // Time held until here @@ -1979,7 +1985,8 @@ void SlideShowImpl::notifySlideAnimationsEnded() // timeout involved. aNotificationEvents.mpImmediateEvent = makeEvent( boost::bind( - &SlideShowImpl::notifySlideEnded, this, false ) ); + &SlideShowImpl::notifySlideEnded, this, false ), + "SlideShowImpl::notifySlideEnded"); } } -- cgit From 5c6ea15c19a15f758abeccf5cb3515e211c079cc Mon Sep 17 00:00:00 2001 From: Andre Fischer Date: Wed, 6 May 2009 11:40:04 +0000 Subject: #i98792# Removed second frame synchronization. --- slideshow/source/engine/slideshowimpl.cxx | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'slideshow/source/engine/slideshowimpl.cxx') diff --git a/slideshow/source/engine/slideshowimpl.cxx b/slideshow/source/engine/slideshowimpl.cxx index 1ab20f7f294e..45b94ac26501 100644 --- a/slideshow/source/engine/slideshowimpl.cxx +++ b/slideshow/source/engine/slideshowimpl.cxx @@ -148,6 +148,12 @@ public: */ void Deactivate (void); + /** Return the current time of the timer. It is not synchronized with + any other timer so its absolute values are of no concern. Typically + used during debugging to measure durations. + */ + double GetCurrentTime (void) const; + private: /** The timer that is used for synchronization is independent from the one used by SlideShowImpl: it is not paused or modified by @@ -169,6 +175,8 @@ private: }; + + /****************************************************************************** SlideShowImpl @@ -1782,7 +1790,6 @@ sal_Bool SlideShowImpl::update( double & nNextTimeout ) maActivitiesQueue.processDequeued(); // commit frame to screen - maFrameSynchronization.Synchronize(); maScreenUpdater.commitUpdates(); } // Time held until here @@ -2171,6 +2178,13 @@ void FrameSynchronization::Deactivate (void) + +double FrameSynchronization::GetCurrentTime (void) const +{ + return maTimer.getElapsedTime(); +} + + } // anon namespace namespace sdecl = comphelper::service_decl; -- cgit From 5caa4326854d346e40b9d052255effa446e54513 Mon Sep 17 00:00:00 2001 From: Andre Fischer Date: Wed, 14 Oct 2009 12:38:02 +0000 Subject: #i48179# Fixed stepping back for animations with active auto_reverse. --- slideshow/source/engine/slideshowimpl.cxx | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'slideshow/source/engine/slideshowimpl.cxx') diff --git a/slideshow/source/engine/slideshowimpl.cxx b/slideshow/source/engine/slideshowimpl.cxx index 45b94ac26501..b042014af9c6 100644 --- a/slideshow/source/engine/slideshowimpl.cxx +++ b/slideshow/source/engine/slideshowimpl.cxx @@ -71,6 +71,7 @@ #include #include #include +#include #include #include #include @@ -509,11 +510,14 @@ struct SlideShowImpl::SeparateListenerImpl : public EventHandler, // directly, but queue an event. handleEvent() // might be called from e.g. // showNext(), and notifySlideAnimationsEnded() must not be called - // in recursion. - mrEventQueue.addEvent( - makeEvent( boost::bind( &SlideShowImpl::notifySlideAnimationsEnded, - boost::ref(mrShow) ), - "SlideShowImpl::notifySlideAnimationsEnded")); + // in recursion. Note that the event is scheduled for the next + // frame so that its expensive execution does not come in between + // sprite hiding and shape redraw (at the end of the animation of a + // shape), which would cause a flicker. + mrEventQueue.addEventForNextRound( + makeEvent( + boost::bind( &SlideShowImpl::notifySlideAnimationsEnded, boost::ref(mrShow) ), + "SlideShowImpl::notifySlideAnimationsEnded")); return true; } @@ -2079,7 +2083,7 @@ void SlideShowImpl::notifySlideEnded (const bool bReverse) boost::bind( &presentation::XSlideShowListener::slideEnded, _1, - bReverse) ); + bReverse)); } bool SlideShowImpl::notifyHyperLinkClicked( rtl::OUString const& hyperLink ) -- cgit From 83168b2ff90cf04ee9f5b5f6408d184f2709f26e Mon Sep 17 00:00:00 2001 From: Andre Fischer Date: Fri, 16 Oct 2009 13:24:22 +0000 Subject: #i48179# Resolved merge problems. --- slideshow/source/engine/slideshowimpl.cxx | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'slideshow/source/engine/slideshowimpl.cxx') diff --git a/slideshow/source/engine/slideshowimpl.cxx b/slideshow/source/engine/slideshowimpl.cxx index 9a4878f43d59..88637a431282 100644 --- a/slideshow/source/engine/slideshowimpl.cxx +++ b/slideshow/source/engine/slideshowimpl.cxx @@ -1954,11 +1954,7 @@ void SlideShowImpl::notifySlideAnimationsEnded() // schedule a slide end event, with automatic mode's // delay aNotificationEvents = makeInterruptableDelay( -<<<<<<< .working - boost::bind( &SlideShowImpl::notifySlideEnded, this, false ), -======= - boost::bind( boost::mem_fn(&SlideShowImpl::notifySlideEnded), this ), ->>>>>>> .merge-right.r276697 + boost::bind( boost::mem_fn(&SlideShowImpl::notifySlideEnded), this, false ), maEventMultiplexer.getAutomaticTimeout() ); } else -- cgit From d4813204c6341ee55f51975da46ac12a1a3069bc Mon Sep 17 00:00:00 2001 From: Andre Fischer Date: Tue, 20 Oct 2009 08:39:11 +0000 Subject: #i48179# Resolved some compilation problems. --- slideshow/source/engine/slideshowimpl.cxx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'slideshow/source/engine/slideshowimpl.cxx') diff --git a/slideshow/source/engine/slideshowimpl.cxx b/slideshow/source/engine/slideshowimpl.cxx index 88637a431282..18b3a8ef4102 100644 --- a/slideshow/source/engine/slideshowimpl.cxx +++ b/slideshow/source/engine/slideshowimpl.cxx @@ -1216,8 +1216,8 @@ sal_Bool SlideShowImpl::previousEffect() throw (uno::RuntimeException) { return maEffectRewinder.rewind( maScreenUpdater.createLock(false), - ::boost::bind(&SlideShowImpl::redisplayCurrentSlide, this), - ::boost::bind(&SlideShowImpl::rewindEffectToPreviousSlide, this)); + ::boost::bind(&SlideShowImpl::redisplayCurrentSlide, this), + ::boost::bind(&SlideShowImpl::rewindEffectToPreviousSlide, this)); } } @@ -2080,10 +2080,10 @@ void SlideShowImpl::notifySlideEnded (const bool bReverse) // GIF) will not be stopped. maListenerContainer.forEach( - boost::bind( + boost::bind( &presentation::XSlideShowListener::slideEnded, _1, - bReverse)); + sal_Bool(bReverse))); } bool SlideShowImpl::notifyHyperLinkClicked( rtl::OUString const& hyperLink ) -- cgit From 1ae23cece0bf35ea52a15c66519a34c43ac57937 Mon Sep 17 00:00:00 2001 From: Andre Fischer Date: Tue, 3 Nov 2009 09:26:54 +0000 Subject: #i48179# Fixed some Solaris compilation problems. --- slideshow/source/engine/slideshowimpl.cxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'slideshow/source/engine/slideshowimpl.cxx') diff --git a/slideshow/source/engine/slideshowimpl.cxx b/slideshow/source/engine/slideshowimpl.cxx index 18b3a8ef4102..109e64ca63c1 100644 --- a/slideshow/source/engine/slideshowimpl.cxx +++ b/slideshow/source/engine/slideshowimpl.cxx @@ -1216,8 +1216,8 @@ sal_Bool SlideShowImpl::previousEffect() throw (uno::RuntimeException) { return maEffectRewinder.rewind( maScreenUpdater.createLock(false), - ::boost::bind(&SlideShowImpl::redisplayCurrentSlide, this), - ::boost::bind(&SlideShowImpl::rewindEffectToPreviousSlide, this)); + ::boost::bind(::boost::mem_fn(&SlideShowImpl::redisplayCurrentSlide), this), + ::boost::bind(::boost::mem_fn(&SlideShowImpl::rewindEffectToPreviousSlide), this)); } } @@ -2081,7 +2081,7 @@ void SlideShowImpl::notifySlideEnded (const bool bReverse) maListenerContainer.forEach( boost::bind( - &presentation::XSlideShowListener::slideEnded, + ::boost::mem_fn(&presentation::XSlideShowListener::slideEnded), _1, sal_Bool(bReverse))); } -- cgit