1*70f497fbSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*70f497fbSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*70f497fbSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*70f497fbSAndrew Rist  * distributed with this work for additional information
6*70f497fbSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*70f497fbSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*70f497fbSAndrew Rist  * "License"); you may not use this file except in compliance
9*70f497fbSAndrew Rist  * with the License.  You may obtain a copy of the License at
10*70f497fbSAndrew Rist  *
11*70f497fbSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*70f497fbSAndrew Rist  *
13*70f497fbSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*70f497fbSAndrew Rist  * software distributed under the License is distributed on an
15*70f497fbSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*70f497fbSAndrew Rist  * KIND, either express or implied.  See the License for the
17*70f497fbSAndrew Rist  * specific language governing permissions and limitations
18*70f497fbSAndrew Rist  * under the License.
19*70f497fbSAndrew Rist  *
20*70f497fbSAndrew Rist  *************************************************************/
21*70f497fbSAndrew Rist 
22*70f497fbSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_slideshow.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir // must be first
28cdf0e10cSrcweir #include <canvas/debug.hxx>
29cdf0e10cSrcweir #include <canvas/verbosetrace.hxx>
30cdf0e10cSrcweir 
31cdf0e10cSrcweir #include <comphelper/anytostring.hxx>
32cdf0e10cSrcweir #include <cppuhelper/exc_hlp.hxx>
33cdf0e10cSrcweir 
34cdf0e10cSrcweir #include "slideshowexceptions.hxx"
35cdf0e10cSrcweir #include "activity.hxx"
36cdf0e10cSrcweir #include "activitiesqueue.hxx"
37cdf0e10cSrcweir 
38cdf0e10cSrcweir #include <boost/bind.hpp>
39cdf0e10cSrcweir #include <algorithm>
40cdf0e10cSrcweir 
41cdf0e10cSrcweir 
42cdf0e10cSrcweir using namespace ::com::sun::star;
43cdf0e10cSrcweir 
44cdf0e10cSrcweir namespace slideshow
45cdf0e10cSrcweir {
46cdf0e10cSrcweir     namespace internal
47cdf0e10cSrcweir     {
ActivitiesQueue(const::boost::shared_ptr<::canvas::tools::ElapsedTime> & pPresTimer)48cdf0e10cSrcweir         ActivitiesQueue::ActivitiesQueue(
49cdf0e10cSrcweir           const ::boost::shared_ptr< ::canvas::tools::ElapsedTime >& pPresTimer ) :
50cdf0e10cSrcweir             mpTimer( pPresTimer ),
51cdf0e10cSrcweir             maCurrentActivitiesWaiting(),
52cdf0e10cSrcweir             maCurrentActivitiesReinsert(),
53cdf0e10cSrcweir             maDequeuedActivities()
54cdf0e10cSrcweir         {
55cdf0e10cSrcweir         }
56cdf0e10cSrcweir 
~ActivitiesQueue()57cdf0e10cSrcweir         ActivitiesQueue::~ActivitiesQueue()
58cdf0e10cSrcweir         {
59cdf0e10cSrcweir             // dispose all queue entries
60cdf0e10cSrcweir             try
61cdf0e10cSrcweir             {
62cdf0e10cSrcweir                 std::for_each( maCurrentActivitiesWaiting.begin(),
63cdf0e10cSrcweir                                maCurrentActivitiesWaiting.end(),
64cdf0e10cSrcweir                                boost::mem_fn( &Disposable::dispose ) );
65cdf0e10cSrcweir                 std::for_each( maCurrentActivitiesReinsert.begin(),
66cdf0e10cSrcweir                                maCurrentActivitiesReinsert.end(),
67cdf0e10cSrcweir                                boost::mem_fn( &Disposable::dispose ) );
68cdf0e10cSrcweir             }
69cdf0e10cSrcweir             catch (uno::Exception &)
70cdf0e10cSrcweir             {
71cdf0e10cSrcweir                 OSL_ENSURE( false, rtl::OUStringToOString(
72cdf0e10cSrcweir                                 comphelper::anyToString(
73cdf0e10cSrcweir                                     cppu::getCaughtException() ),
74cdf0e10cSrcweir                                 RTL_TEXTENCODING_UTF8 ).getStr() );
75cdf0e10cSrcweir             }
76cdf0e10cSrcweir         }
77cdf0e10cSrcweir 
addActivity(const ActivitySharedPtr & pActivity)78cdf0e10cSrcweir         bool ActivitiesQueue::addActivity( const ActivitySharedPtr& pActivity )
79cdf0e10cSrcweir         {
80cdf0e10cSrcweir             OSL_ENSURE( pActivity, "ActivitiesQueue::addActivity: activity ptr NULL" );
81cdf0e10cSrcweir 
82cdf0e10cSrcweir             if( !pActivity )
83cdf0e10cSrcweir                 return false;
84cdf0e10cSrcweir 
85cdf0e10cSrcweir             // add entry to waiting list
86cdf0e10cSrcweir             maCurrentActivitiesWaiting.push_back( pActivity );
87cdf0e10cSrcweir 
88cdf0e10cSrcweir             return true;
89cdf0e10cSrcweir         }
90cdf0e10cSrcweir 
process()91cdf0e10cSrcweir         void ActivitiesQueue::process()
92cdf0e10cSrcweir         {
93cdf0e10cSrcweir             VERBOSE_TRACE( "ActivitiesQueue: outer loop heartbeat" );
94cdf0e10cSrcweir 
95cdf0e10cSrcweir             // accumulate time lag for all activities, and lag time
96cdf0e10cSrcweir             // base if necessary:
97cdf0e10cSrcweir             ActivityQueue::const_iterator iPos(
98cdf0e10cSrcweir                 maCurrentActivitiesWaiting.begin() );
99cdf0e10cSrcweir             const ActivityQueue::const_iterator iEnd(
100cdf0e10cSrcweir                 maCurrentActivitiesWaiting.end() );
101cdf0e10cSrcweir             double fLag = 0.0;
102cdf0e10cSrcweir             for ( ; iPos != iEnd; ++iPos )
103cdf0e10cSrcweir                 fLag = std::max<double>( fLag, (*iPos)->calcTimeLag() );
104cdf0e10cSrcweir             if (fLag > 0.0)
105cdf0e10cSrcweir             {
106cdf0e10cSrcweir                 mpTimer->adjustTimer( -fLag );
107cdf0e10cSrcweir             }
108cdf0e10cSrcweir 
109cdf0e10cSrcweir             // process list of activities
110cdf0e10cSrcweir             while( !maCurrentActivitiesWaiting.empty() )
111cdf0e10cSrcweir             {
112cdf0e10cSrcweir                 // process topmost activity
113cdf0e10cSrcweir                 ActivitySharedPtr pActivity( maCurrentActivitiesWaiting.front() );
114cdf0e10cSrcweir                 maCurrentActivitiesWaiting.pop_front();
115cdf0e10cSrcweir 
116cdf0e10cSrcweir                 bool bReinsert( false );
117cdf0e10cSrcweir 
118cdf0e10cSrcweir                 try
119cdf0e10cSrcweir                 {
120cdf0e10cSrcweir                     // fire up activity
121cdf0e10cSrcweir                     bReinsert = pActivity->perform();
122cdf0e10cSrcweir                 }
123cdf0e10cSrcweir                 catch( uno::RuntimeException& )
124cdf0e10cSrcweir                 {
125cdf0e10cSrcweir                     throw;
126cdf0e10cSrcweir                 }
127cdf0e10cSrcweir                 catch( uno::Exception& )
128cdf0e10cSrcweir                 {
129cdf0e10cSrcweir                     // catch anything here, we don't want
130cdf0e10cSrcweir                     // to leave this scope under _any_
131cdf0e10cSrcweir                     // circumstance. Although, do _not_
132cdf0e10cSrcweir                     // reinsert an activity that threw
133cdf0e10cSrcweir                     // once.
134cdf0e10cSrcweir 
135cdf0e10cSrcweir                     // NOTE: we explicitely don't catch(...) here,
136cdf0e10cSrcweir                     // since this will also capture segmentation
137cdf0e10cSrcweir                     // violations and the like. In such a case, we
138cdf0e10cSrcweir                     // still better let our clients now...
139cdf0e10cSrcweir                     OSL_ENSURE( false,
140cdf0e10cSrcweir                                 rtl::OUStringToOString(
141cdf0e10cSrcweir                                     comphelper::anyToString( cppu::getCaughtException() ),
142cdf0e10cSrcweir                                     RTL_TEXTENCODING_UTF8 ).getStr() );
143cdf0e10cSrcweir                 }
144cdf0e10cSrcweir                 catch( SlideShowException& )
145cdf0e10cSrcweir                 {
146cdf0e10cSrcweir                     // catch anything here, we don't want
147cdf0e10cSrcweir                     // to leave this scope under _any_
148cdf0e10cSrcweir                     // circumstance. Although, do _not_
149cdf0e10cSrcweir                     // reinsert an activity that threw
150cdf0e10cSrcweir                     // once.
151cdf0e10cSrcweir 
152cdf0e10cSrcweir                     // NOTE: we explicitely don't catch(...) here,
153cdf0e10cSrcweir                     // since this will also capture segmentation
154cdf0e10cSrcweir                     // violations and the like. In such a case, we
155cdf0e10cSrcweir                     // still better let our clients now...
156cdf0e10cSrcweir                     OSL_TRACE( "::presentation::internal::ActivitiesQueue: Activity threw a SlideShowException, removing from ring" );
157cdf0e10cSrcweir                 }
158cdf0e10cSrcweir 
159cdf0e10cSrcweir                 if( bReinsert )
160cdf0e10cSrcweir                     maCurrentActivitiesReinsert.push_back( pActivity );
161cdf0e10cSrcweir                 else
162cdf0e10cSrcweir                     maDequeuedActivities.push_back( pActivity );
163cdf0e10cSrcweir 
164cdf0e10cSrcweir                 VERBOSE_TRACE( "ActivitiesQueue: inner loop heartbeat" );
165cdf0e10cSrcweir             }
166cdf0e10cSrcweir 
167cdf0e10cSrcweir             if( !maCurrentActivitiesReinsert.empty() )
168cdf0e10cSrcweir             {
169cdf0e10cSrcweir                 // reinsert all processed, but not finished
170cdf0e10cSrcweir                 // activities back to waiting queue. With swap(),
171cdf0e10cSrcweir                 // we kill two birds with one stone: we reuse the
172cdf0e10cSrcweir                 // list nodes, and we clear the
173cdf0e10cSrcweir                 // maCurrentActivitiesReinsert list
174cdf0e10cSrcweir                 maCurrentActivitiesWaiting.swap( maCurrentActivitiesReinsert );
175cdf0e10cSrcweir             }
176cdf0e10cSrcweir         }
177cdf0e10cSrcweir 
processDequeued()178cdf0e10cSrcweir         void ActivitiesQueue::processDequeued()
179cdf0e10cSrcweir         {
180cdf0e10cSrcweir             // notify all dequeued activities from last round
181cdf0e10cSrcweir             ::std::for_each( maDequeuedActivities.begin(),
182cdf0e10cSrcweir                              maDequeuedActivities.end(),
183cdf0e10cSrcweir                              ::boost::mem_fn( &Activity::dequeued ) );
184cdf0e10cSrcweir             maDequeuedActivities.clear();
185cdf0e10cSrcweir         }
186cdf0e10cSrcweir 
isEmpty() const187cdf0e10cSrcweir         bool ActivitiesQueue::isEmpty() const
188cdf0e10cSrcweir         {
189cdf0e10cSrcweir             return maCurrentActivitiesWaiting.empty() && maCurrentActivitiesReinsert.empty();
190cdf0e10cSrcweir         }
191cdf0e10cSrcweir 
clear()192cdf0e10cSrcweir         void ActivitiesQueue::clear()
193cdf0e10cSrcweir         {
194cdf0e10cSrcweir             // dequeue all entries:
195cdf0e10cSrcweir             std::for_each( maCurrentActivitiesWaiting.begin(),
196cdf0e10cSrcweir                            maCurrentActivitiesWaiting.end(),
197cdf0e10cSrcweir                            boost::mem_fn( &Activity::dequeued ) );
198cdf0e10cSrcweir             ActivityQueue().swap( maCurrentActivitiesWaiting );
199cdf0e10cSrcweir 
200cdf0e10cSrcweir             std::for_each( maCurrentActivitiesReinsert.begin(),
201cdf0e10cSrcweir                            maCurrentActivitiesReinsert.end(),
202cdf0e10cSrcweir                            boost::mem_fn( &Activity::dequeued ) );
203cdf0e10cSrcweir             ActivityQueue().swap( maCurrentActivitiesReinsert );
204cdf0e10cSrcweir         }
205cdf0e10cSrcweir     }
206cdf0e10cSrcweir }
207