1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_slideshow.hxx" 30 31 // must be first 32 #include <canvas/debug.hxx> 33 #include <canvas/verbosetrace.hxx> 34 35 #include "eventqueue.hxx" 36 #include "animationaudionode.hxx" 37 #include "delayevent.hxx" 38 #include "tools.hxx" 39 #include "nodetools.hxx" 40 #include "boost/bind.hpp" 41 42 using namespace com::sun::star; 43 44 namespace slideshow { 45 namespace internal { 46 47 AnimationAudioNode::AnimationAudioNode( 48 const uno::Reference< animations::XAnimationNode >& xNode, 49 const BaseContainerNodeSharedPtr& rParent, 50 const NodeContext& rContext ) 51 : BaseNode( xNode, rParent, rContext ), 52 mxAudioNode( xNode, uno::UNO_QUERY_THROW ), 53 maSoundURL(), 54 mpPlayer() 55 { 56 mxAudioNode->getSource() >>= maSoundURL; 57 58 OSL_ENSURE( maSoundURL.getLength(), 59 "could not extract sound source URL/empty URL string" ); 60 61 ENSURE_OR_THROW( getContext().mxComponentContext.is(), 62 "Invalid component context" ); 63 } 64 65 void AnimationAudioNode::dispose() 66 { 67 resetPlayer(); 68 mxAudioNode.clear(); 69 BaseNode::dispose(); 70 } 71 72 void AnimationAudioNode::activate_st() 73 { 74 createPlayer(); 75 76 AnimationEventHandlerSharedPtr aHandler( 77 boost::dynamic_pointer_cast<AnimationEventHandler>( getSelf() ) ); 78 OSL_ENSURE( aHandler, 79 "could not cast self to AnimationEventHandler?" ); 80 getContext().mrEventMultiplexer.addCommandStopAudioHandler( aHandler ); 81 82 if (mpPlayer && mpPlayer->startPlayback()) 83 { 84 // TODO(F2): Handle end time attribute, too 85 if( getXAnimationNode()->getDuration().hasValue() ) 86 { 87 scheduleDeactivationEvent(); 88 } 89 else 90 { 91 // no node duration. Take inherent media time, then 92 scheduleDeactivationEvent( 93 makeDelay( boost::bind( &AnimationNode::deactivate, getSelf() ), 94 mpPlayer->getDuration(), 95 "AnimationAudioNode::deactivate with delay") ); 96 } 97 } 98 else 99 { 100 // deactivate ASAP: 101 scheduleDeactivationEvent( 102 makeEvent( boost::bind( &AnimationNode::deactivate, getSelf() ), 103 "AnimationAudioNode::deactivate without delay") ); 104 } 105 } 106 107 // TODO(F2): generate deactivation event, when sound 108 // is over 109 110 void AnimationAudioNode::deactivate_st( NodeState /*eDestState*/ ) 111 { 112 AnimationEventHandlerSharedPtr aHandler( 113 boost::dynamic_pointer_cast<AnimationEventHandler>( getSelf() ) ); 114 OSL_ENSURE( aHandler, 115 "could not cas self to AnimationEventHandler?" ); 116 getContext().mrEventMultiplexer.removeCommandStopAudioHandler( aHandler ); 117 118 // force-end sound 119 if (mpPlayer) 120 { 121 mpPlayer->stopPlayback(); 122 resetPlayer(); 123 } 124 125 // notify _after_ state change: 126 getContext().mrEventQueue.addEvent( 127 makeEvent( boost::bind( &EventMultiplexer::notifyAudioStopped, 128 boost::ref(getContext().mrEventMultiplexer), 129 getSelf() ), 130 "AnimationAudioNode::notifyAudioStopped") ); 131 } 132 133 bool AnimationAudioNode::hasPendingAnimation() const 134 { 135 // force slide to use the animation framework 136 // (otherwise, a single sound on the slide would 137 // not be played). 138 return true; 139 } 140 141 void AnimationAudioNode::createPlayer() const 142 { 143 if (mpPlayer) 144 return; 145 146 try 147 { 148 mpPlayer = SoundPlayer::create( getContext().mrEventMultiplexer, 149 maSoundURL, 150 getContext().mxComponentContext ); 151 } 152 catch( lang::NoSupportException& ) 153 { 154 // catch possible exceptions from SoundPlayer, 155 // since being not able to playback the sound 156 // is not a hard error here (remainder of the 157 // animations should still work). 158 } 159 } 160 161 void AnimationAudioNode::resetPlayer() const 162 { 163 if (mpPlayer) 164 { 165 mpPlayer->stopPlayback(); 166 mpPlayer->dispose(); 167 mpPlayer.reset(); 168 } 169 } 170 171 bool AnimationAudioNode::handleAnimationEvent( 172 const AnimationNodeSharedPtr& /*rNode*/ ) 173 { 174 // TODO(F2): for now we support only STOPAUDIO events. 175 deactivate(); 176 return true; 177 } 178 179 } // namespace internal 180 } // namespace presentation 181 182