1*c142477cSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*c142477cSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*c142477cSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*c142477cSAndrew Rist  * distributed with this work for additional information
6*c142477cSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*c142477cSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*c142477cSAndrew Rist  * "License"); you may not use this file except in compliance
9*c142477cSAndrew Rist  * with the License.  You may obtain a copy of the License at
10*c142477cSAndrew Rist  *
11*c142477cSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*c142477cSAndrew Rist  *
13*c142477cSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*c142477cSAndrew Rist  * software distributed under the License is distributed on an
15*c142477cSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*c142477cSAndrew Rist  * KIND, either express or implied.  See the License for the
17*c142477cSAndrew Rist  * specific language governing permissions and limitations
18*c142477cSAndrew Rist  * under the License.
19*c142477cSAndrew Rist  *
20*c142477cSAndrew Rist  *************************************************************/
21*c142477cSAndrew Rist 
22*c142477cSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_sdext.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include "PresenterTimer.hxx"
28cdf0e10cSrcweir #include <osl/doublecheckedlocking.h>
29cdf0e10cSrcweir #include <osl/thread.hxx>
30cdf0e10cSrcweir #include <boost/bind.hpp>
31cdf0e10cSrcweir #include <boost/function.hpp>
32cdf0e10cSrcweir #include <boost/enable_shared_from_this.hpp>
33cdf0e10cSrcweir #include <set>
34cdf0e10cSrcweir 
35cdf0e10cSrcweir using namespace ::com::sun::star;
36cdf0e10cSrcweir using namespace ::com::sun::star::uno;
37cdf0e10cSrcweir 
38cdf0e10cSrcweir #define A2S(pString) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(pString)))
39cdf0e10cSrcweir 
40cdf0e10cSrcweir namespace sdext { namespace presenter {
41cdf0e10cSrcweir 
42cdf0e10cSrcweir namespace {
43cdf0e10cSrcweir class TimerTask
44cdf0e10cSrcweir {
45cdf0e10cSrcweir public:
46cdf0e10cSrcweir     TimerTask (
47cdf0e10cSrcweir         const PresenterTimer::Task& rTask,
48cdf0e10cSrcweir         const TimeValue& rDueTime,
49cdf0e10cSrcweir         const sal_Int64 nRepeatIntervall,
50cdf0e10cSrcweir         const sal_Int32 nTaskId);
~TimerTask(void)51cdf0e10cSrcweir     ~TimerTask (void) {}
52cdf0e10cSrcweir 
53cdf0e10cSrcweir     PresenterTimer::Task maTask;
54cdf0e10cSrcweir     TimeValue maDueTime;
55cdf0e10cSrcweir     const sal_Int64 mnRepeatIntervall;
56cdf0e10cSrcweir     const sal_Int32 mnTaskId;
57cdf0e10cSrcweir     bool mbIsCanceled;
58cdf0e10cSrcweir };
59cdf0e10cSrcweir 
60cdf0e10cSrcweir typedef ::boost::shared_ptr<TimerTask> SharedTimerTask;
61cdf0e10cSrcweir 
62cdf0e10cSrcweir 
63cdf0e10cSrcweir class TimerTaskComparator
64cdf0e10cSrcweir {
65cdf0e10cSrcweir public:
operator ()(const SharedTimerTask & rpTask1,const SharedTimerTask & rpTask2)66cdf0e10cSrcweir     bool operator() (const SharedTimerTask& rpTask1, const SharedTimerTask& rpTask2)
67cdf0e10cSrcweir     {
68cdf0e10cSrcweir         return rpTask1->maDueTime.Seconds < rpTask2->maDueTime.Seconds
69cdf0e10cSrcweir             || (rpTask1->maDueTime.Seconds == rpTask2->maDueTime.Seconds
70cdf0e10cSrcweir                 && rpTask1->maDueTime.Nanosec < rpTask2->maDueTime.Nanosec);
71cdf0e10cSrcweir     }
72cdf0e10cSrcweir };
73cdf0e10cSrcweir 
74cdf0e10cSrcweir 
75cdf0e10cSrcweir 
76cdf0e10cSrcweir 
77cdf0e10cSrcweir /** Queue all scheduled tasks and process them when their time has come.
78cdf0e10cSrcweir */
79cdf0e10cSrcweir class TimerScheduler
80cdf0e10cSrcweir     : public ::boost::enable_shared_from_this<TimerScheduler>,
81cdf0e10cSrcweir       public ::osl::Thread
82cdf0e10cSrcweir {
83cdf0e10cSrcweir public:
84cdf0e10cSrcweir     static ::boost::shared_ptr<TimerScheduler> Instance (void);
85cdf0e10cSrcweir     static SharedTimerTask CreateTimerTask (
86cdf0e10cSrcweir         const PresenterTimer::Task& rTask,
87cdf0e10cSrcweir         const TimeValue& rDueTime,
88cdf0e10cSrcweir         const sal_Int64 nRepeatIntervall);
89cdf0e10cSrcweir 
90cdf0e10cSrcweir     void ScheduleTask (const SharedTimerTask& rpTask);
91cdf0e10cSrcweir     void CancelTask (const sal_Int32 nTaskId);
92cdf0e10cSrcweir 
93cdf0e10cSrcweir     static bool GetCurrentTime (TimeValue& rCurrentTime);
94cdf0e10cSrcweir     static sal_Int64 GetTimeDifference (
95cdf0e10cSrcweir         const TimeValue& rTargetTime,
96cdf0e10cSrcweir         const TimeValue& rCurrentTime);
97cdf0e10cSrcweir     static void ConvertToTimeValue (
98cdf0e10cSrcweir         TimeValue& rTimeValue,
99cdf0e10cSrcweir         const sal_Int64 nTimeDifference);
100cdf0e10cSrcweir     static sal_Int64 ConvertFromTimeValue (
101cdf0e10cSrcweir         const TimeValue& rTimeValue);
102cdf0e10cSrcweir 
103cdf0e10cSrcweir private:
104cdf0e10cSrcweir     static ::boost::shared_ptr<TimerScheduler> mpInstance;
105cdf0e10cSrcweir     static ::osl::Mutex maInstanceMutex;
106cdf0e10cSrcweir     static sal_Int32 mnTaskId;
107cdf0e10cSrcweir 
108cdf0e10cSrcweir     ::osl::Mutex maTaskContainerMutex;
109cdf0e10cSrcweir     typedef ::std::set<SharedTimerTask,TimerTaskComparator> TaskContainer;
110cdf0e10cSrcweir     TaskContainer maScheduledTasks;
111cdf0e10cSrcweir     bool mbIsRunning;
112cdf0e10cSrcweir     ::osl::Mutex maCurrentTaskMutex;
113cdf0e10cSrcweir     SharedTimerTask mpCurrentTask;
114cdf0e10cSrcweir 
115cdf0e10cSrcweir     static void Release (void);
116cdf0e10cSrcweir 
117cdf0e10cSrcweir     TimerScheduler (void);
118cdf0e10cSrcweir     virtual ~TimerScheduler (void);
operator ()(TimerScheduler * pScheduler)119cdf0e10cSrcweir     class Deleter {public: void operator () (TimerScheduler* pScheduler) { delete pScheduler; } };
120cdf0e10cSrcweir     friend class Deleter;
121cdf0e10cSrcweir 
122cdf0e10cSrcweir     virtual void SAL_CALL run (void);
123cdf0e10cSrcweir     virtual void SAL_CALL onTerminated (void);
124cdf0e10cSrcweir };
125cdf0e10cSrcweir 
126cdf0e10cSrcweir 
127cdf0e10cSrcweir 
128cdf0e10cSrcweir 
129cdf0e10cSrcweir bool GetDateTime (oslDateTime& rDateTime);
130cdf0e10cSrcweir } // end of anonymous namespace
131cdf0e10cSrcweir 
132cdf0e10cSrcweir 
133cdf0e10cSrcweir //===== PresenterTimer ========================================================
134cdf0e10cSrcweir 
ScheduleSingleTaskRelative(const Task & rTask,const sal_Int64 nDelay)135cdf0e10cSrcweir sal_Int32 PresenterTimer::ScheduleSingleTaskRelative (
136cdf0e10cSrcweir     const Task& rTask,
137cdf0e10cSrcweir     const sal_Int64 nDelay)
138cdf0e10cSrcweir {
139cdf0e10cSrcweir     return ScheduleRepeatedTask(rTask, nDelay, 0);
140cdf0e10cSrcweir }
141cdf0e10cSrcweir 
142cdf0e10cSrcweir 
143cdf0e10cSrcweir 
144cdf0e10cSrcweir 
ScheduleSingleTaskAbsolute(const Task & rTask,const TimeValue & rDueTime)145cdf0e10cSrcweir sal_Int32 PresenterTimer::ScheduleSingleTaskAbsolute (
146cdf0e10cSrcweir     const Task& rTask,
147cdf0e10cSrcweir     const TimeValue& rDueTime)
148cdf0e10cSrcweir {
149cdf0e10cSrcweir     SharedTimerTask pTask (TimerScheduler::CreateTimerTask(rTask, rDueTime, 0));
150cdf0e10cSrcweir     TimerScheduler::Instance()->ScheduleTask(pTask);
151cdf0e10cSrcweir     return pTask->mnTaskId;
152cdf0e10cSrcweir }
153cdf0e10cSrcweir 
154cdf0e10cSrcweir 
155cdf0e10cSrcweir 
156cdf0e10cSrcweir 
ScheduleRepeatedTask(const Task & rTask,const sal_Int64 nDelay,const sal_Int64 nIntervall)157cdf0e10cSrcweir sal_Int32 PresenterTimer::ScheduleRepeatedTask (
158cdf0e10cSrcweir     const Task& rTask,
159cdf0e10cSrcweir     const sal_Int64 nDelay,
160cdf0e10cSrcweir     const sal_Int64 nIntervall)
161cdf0e10cSrcweir {
162cdf0e10cSrcweir     TimeValue aCurrentTime;
163cdf0e10cSrcweir     if (TimerScheduler::GetCurrentTime(aCurrentTime))
164cdf0e10cSrcweir     {
165cdf0e10cSrcweir         TimeValue aDueTime;
166cdf0e10cSrcweir         TimerScheduler::ConvertToTimeValue(
167cdf0e10cSrcweir             aDueTime,
168cdf0e10cSrcweir             TimerScheduler::ConvertFromTimeValue (aCurrentTime) + nDelay);
169cdf0e10cSrcweir         SharedTimerTask pTask (TimerScheduler::CreateTimerTask(rTask, aDueTime, nIntervall));
170cdf0e10cSrcweir         TimerScheduler::Instance()->ScheduleTask(pTask);
171cdf0e10cSrcweir         return pTask->mnTaskId;
172cdf0e10cSrcweir     }
173cdf0e10cSrcweir 
174cdf0e10cSrcweir     return NotAValidTaskId;
175cdf0e10cSrcweir }
176cdf0e10cSrcweir 
177cdf0e10cSrcweir 
178cdf0e10cSrcweir 
179cdf0e10cSrcweir 
CancelTask(const sal_Int32 nTaskId)180cdf0e10cSrcweir void PresenterTimer::CancelTask (const sal_Int32 nTaskId)
181cdf0e10cSrcweir {
182cdf0e10cSrcweir     return TimerScheduler::Instance()->CancelTask(nTaskId);
183cdf0e10cSrcweir }
184cdf0e10cSrcweir 
185cdf0e10cSrcweir 
186cdf0e10cSrcweir 
187cdf0e10cSrcweir 
188cdf0e10cSrcweir //===== TimerScheduler ========================================================
189cdf0e10cSrcweir 
190cdf0e10cSrcweir ::boost::shared_ptr<TimerScheduler> TimerScheduler::mpInstance;
191cdf0e10cSrcweir ::osl::Mutex TimerScheduler::maInstanceMutex;
192cdf0e10cSrcweir sal_Int32 TimerScheduler::mnTaskId = PresenterTimer::NotAValidTaskId;
193cdf0e10cSrcweir 
Instance(void)194cdf0e10cSrcweir ::boost::shared_ptr<TimerScheduler> TimerScheduler::Instance (void)
195cdf0e10cSrcweir {
196cdf0e10cSrcweir     ::boost::shared_ptr<TimerScheduler> pInstance = mpInstance;
197cdf0e10cSrcweir     if (pInstance.get() == NULL)
198cdf0e10cSrcweir     {
199cdf0e10cSrcweir         ::osl::MutexGuard aGuard (maInstanceMutex);
200cdf0e10cSrcweir         pInstance = mpInstance;
201cdf0e10cSrcweir         if (pInstance.get() == NULL)
202cdf0e10cSrcweir         {
203cdf0e10cSrcweir             pInstance.reset(new TimerScheduler(), TimerScheduler::Deleter());
204cdf0e10cSrcweir             OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
205cdf0e10cSrcweir             mpInstance = pInstance;
206cdf0e10cSrcweir         }
207cdf0e10cSrcweir     }
208cdf0e10cSrcweir     else
209cdf0e10cSrcweir     {
210cdf0e10cSrcweir         OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
211cdf0e10cSrcweir     }
212cdf0e10cSrcweir     return pInstance;
213cdf0e10cSrcweir }
214cdf0e10cSrcweir 
215cdf0e10cSrcweir 
216cdf0e10cSrcweir 
217cdf0e10cSrcweir 
Release(void)218cdf0e10cSrcweir void TimerScheduler::Release (void)
219cdf0e10cSrcweir {
220cdf0e10cSrcweir     ::osl::MutexGuard aGuard (maInstanceMutex);
221cdf0e10cSrcweir     mpInstance.reset();
222cdf0e10cSrcweir }
223cdf0e10cSrcweir 
224cdf0e10cSrcweir 
225cdf0e10cSrcweir 
226cdf0e10cSrcweir 
TimerScheduler(void)227cdf0e10cSrcweir TimerScheduler::TimerScheduler (void)
228cdf0e10cSrcweir     : maTaskContainerMutex(),
229cdf0e10cSrcweir       maScheduledTasks(),
230cdf0e10cSrcweir       mbIsRunning(false),
231cdf0e10cSrcweir       maCurrentTaskMutex(),
232cdf0e10cSrcweir       mpCurrentTask()
233cdf0e10cSrcweir {
234cdf0e10cSrcweir }
235cdf0e10cSrcweir 
236cdf0e10cSrcweir 
237cdf0e10cSrcweir 
238cdf0e10cSrcweir 
~TimerScheduler(void)239cdf0e10cSrcweir TimerScheduler::~TimerScheduler (void)
240cdf0e10cSrcweir {
241cdf0e10cSrcweir }
242cdf0e10cSrcweir 
243cdf0e10cSrcweir 
244cdf0e10cSrcweir 
CreateTimerTask(const PresenterTimer::Task & rTask,const TimeValue & rDueTime,const sal_Int64 nRepeatIntervall)245cdf0e10cSrcweir SharedTimerTask TimerScheduler::CreateTimerTask (
246cdf0e10cSrcweir     const PresenterTimer::Task& rTask,
247cdf0e10cSrcweir     const TimeValue& rDueTime,
248cdf0e10cSrcweir     const sal_Int64 nRepeatIntervall)
249cdf0e10cSrcweir {
250cdf0e10cSrcweir     return SharedTimerTask(new TimerTask(rTask, rDueTime, nRepeatIntervall, ++mnTaskId));
251cdf0e10cSrcweir }
252cdf0e10cSrcweir 
253cdf0e10cSrcweir 
254cdf0e10cSrcweir 
255cdf0e10cSrcweir 
ScheduleTask(const SharedTimerTask & rpTask)256cdf0e10cSrcweir void TimerScheduler::ScheduleTask (const SharedTimerTask& rpTask)
257cdf0e10cSrcweir {
258cdf0e10cSrcweir     if (rpTask.get() == NULL)
259cdf0e10cSrcweir         return;
260cdf0e10cSrcweir     if (rpTask->mbIsCanceled)
261cdf0e10cSrcweir         return;
262cdf0e10cSrcweir 
263cdf0e10cSrcweir     osl::MutexGuard aGuard (maTaskContainerMutex);
264cdf0e10cSrcweir     maScheduledTasks.insert(rpTask);
265cdf0e10cSrcweir 
266cdf0e10cSrcweir     if ( ! mbIsRunning)
267cdf0e10cSrcweir     {
268cdf0e10cSrcweir         mbIsRunning = true;
269cdf0e10cSrcweir         create();
270cdf0e10cSrcweir     }
271cdf0e10cSrcweir }
272cdf0e10cSrcweir 
273cdf0e10cSrcweir 
274cdf0e10cSrcweir 
275cdf0e10cSrcweir 
CancelTask(const sal_Int32 nTaskId)276cdf0e10cSrcweir void TimerScheduler::CancelTask (const sal_Int32 nTaskId)
277cdf0e10cSrcweir {
278cdf0e10cSrcweir     // Set of scheduled tasks is sorted after their due times, not their
279cdf0e10cSrcweir     // task ids.  Therefore we have to do a linear search for the task to
280cdf0e10cSrcweir     // cancel.
281cdf0e10cSrcweir     {
282cdf0e10cSrcweir         ::osl::MutexGuard aGuard (maTaskContainerMutex);
283cdf0e10cSrcweir         TaskContainer::iterator iTask (maScheduledTasks.begin());
284cdf0e10cSrcweir         TaskContainer::const_iterator iEnd (maScheduledTasks.end());
285cdf0e10cSrcweir         for ( ; iTask!=iEnd; ++iTask)
286cdf0e10cSrcweir         {
287cdf0e10cSrcweir             if ((*iTask)->mnTaskId == nTaskId)
288cdf0e10cSrcweir             {
289cdf0e10cSrcweir                 maScheduledTasks.erase(iTask);
290cdf0e10cSrcweir                 break;
291cdf0e10cSrcweir             }
292cdf0e10cSrcweir         }
293cdf0e10cSrcweir     }
294cdf0e10cSrcweir 
295cdf0e10cSrcweir     // The task that is to be canceled may be currently about to be
296cdf0e10cSrcweir     // processed.  Mark it with a flag that a) prevents a repeating task
297cdf0e10cSrcweir     // from being scheduled again and b) tries to prevent its execution.
298cdf0e10cSrcweir     if (mpCurrentTask.get() != NULL
299cdf0e10cSrcweir         && mpCurrentTask->mnTaskId == nTaskId)
300cdf0e10cSrcweir     {
301cdf0e10cSrcweir         mpCurrentTask->mbIsCanceled = true;
302cdf0e10cSrcweir     }
303cdf0e10cSrcweir 
304cdf0e10cSrcweir     // When the last active task was canceled then the timer can be
305cdf0e10cSrcweir     // stopped.
306cdf0e10cSrcweir     if (maScheduledTasks.size() == 0)
307cdf0e10cSrcweir     {
308cdf0e10cSrcweir         mbIsRunning = false;
309cdf0e10cSrcweir         resume();
310cdf0e10cSrcweir         //        join();
311cdf0e10cSrcweir     }
312cdf0e10cSrcweir }
313cdf0e10cSrcweir 
314cdf0e10cSrcweir 
315cdf0e10cSrcweir 
316cdf0e10cSrcweir 
run(void)317cdf0e10cSrcweir void SAL_CALL TimerScheduler::run (void)
318cdf0e10cSrcweir {
319cdf0e10cSrcweir     while (mbIsRunning)
320cdf0e10cSrcweir     {
321cdf0e10cSrcweir         // Get the current time.
322cdf0e10cSrcweir         TimeValue aCurrentTime;
323cdf0e10cSrcweir         if ( ! GetCurrentTime(aCurrentTime))
324cdf0e10cSrcweir         {
325cdf0e10cSrcweir             // We can not get the current time and thus can not schedule anything.
326cdf0e10cSrcweir             break;
327cdf0e10cSrcweir         }
328cdf0e10cSrcweir 
329cdf0e10cSrcweir         // Restrict access to the maScheduledTasks member to one, mutext
330cdf0e10cSrcweir         // guarded, block.
331cdf0e10cSrcweir         SharedTimerTask pTask;
332cdf0e10cSrcweir         sal_Int64 nDifference = 0;
333cdf0e10cSrcweir         {
334cdf0e10cSrcweir             ::osl::MutexGuard aGuard (maTaskContainerMutex);
335cdf0e10cSrcweir 
336cdf0e10cSrcweir             // There are no more scheduled task.  Leave this loop, function and
337cdf0e10cSrcweir             // live of the TimerScheduler.
338cdf0e10cSrcweir             if (maScheduledTasks.empty())
339cdf0e10cSrcweir                 break;
340cdf0e10cSrcweir 
341cdf0e10cSrcweir             nDifference = GetTimeDifference(
342cdf0e10cSrcweir                 (*maScheduledTasks.begin())->maDueTime,
343cdf0e10cSrcweir                 aCurrentTime);
344cdf0e10cSrcweir             if (nDifference <= 0)
345cdf0e10cSrcweir             {
346cdf0e10cSrcweir                 pTask = *maScheduledTasks.begin();
347cdf0e10cSrcweir                 maScheduledTasks.erase(maScheduledTasks.begin());
348cdf0e10cSrcweir             }
349cdf0e10cSrcweir         }
350cdf0e10cSrcweir 
351cdf0e10cSrcweir         // Acquire a reference to the current task.
352cdf0e10cSrcweir         {
353cdf0e10cSrcweir             ::osl::MutexGuard aGuard (maCurrentTaskMutex);
354cdf0e10cSrcweir             mpCurrentTask = pTask;
355cdf0e10cSrcweir         }
356cdf0e10cSrcweir 
357cdf0e10cSrcweir         if (mpCurrentTask.get() == NULL)
358cdf0e10cSrcweir         {
359cdf0e10cSrcweir             // Wait until the first task becomes due.
360cdf0e10cSrcweir             TimeValue aTimeValue;
361cdf0e10cSrcweir             ConvertToTimeValue(aTimeValue, nDifference);
362cdf0e10cSrcweir             wait(aTimeValue);
363cdf0e10cSrcweir         }
364cdf0e10cSrcweir         else
365cdf0e10cSrcweir         {
366cdf0e10cSrcweir             // Execute task.
367cdf0e10cSrcweir             if ( ! mpCurrentTask->maTask.empty()
368cdf0e10cSrcweir                 && ! mpCurrentTask->mbIsCanceled)
369cdf0e10cSrcweir             {
370cdf0e10cSrcweir                 mpCurrentTask->maTask(aCurrentTime);
371cdf0e10cSrcweir 
372cdf0e10cSrcweir                 // Re-schedule repeating tasks.
373cdf0e10cSrcweir                 if (mpCurrentTask->mnRepeatIntervall > 0)
374cdf0e10cSrcweir                 {
375cdf0e10cSrcweir                     ConvertToTimeValue(
376cdf0e10cSrcweir                         mpCurrentTask->maDueTime,
377cdf0e10cSrcweir                         ConvertFromTimeValue(mpCurrentTask->maDueTime)
378cdf0e10cSrcweir                             + mpCurrentTask->mnRepeatIntervall);
379cdf0e10cSrcweir                     ScheduleTask(mpCurrentTask);
380cdf0e10cSrcweir                 }
381cdf0e10cSrcweir             }
382cdf0e10cSrcweir 
383cdf0e10cSrcweir         }
384cdf0e10cSrcweir 
385cdf0e10cSrcweir         // Release reference to the current task.
386cdf0e10cSrcweir         {
387cdf0e10cSrcweir             ::osl::MutexGuard aGuard (maCurrentTaskMutex);
388cdf0e10cSrcweir             mpCurrentTask.reset();
389cdf0e10cSrcweir         }
390cdf0e10cSrcweir     }
391cdf0e10cSrcweir }
392cdf0e10cSrcweir 
393cdf0e10cSrcweir 
394cdf0e10cSrcweir 
395cdf0e10cSrcweir 
onTerminated(void)396cdf0e10cSrcweir void SAL_CALL TimerScheduler::onTerminated (void)
397cdf0e10cSrcweir {
398cdf0e10cSrcweir     Release();
399cdf0e10cSrcweir }
400cdf0e10cSrcweir 
401cdf0e10cSrcweir 
402cdf0e10cSrcweir 
403cdf0e10cSrcweir 
GetCurrentTime(TimeValue & rCurrentTime)404cdf0e10cSrcweir bool TimerScheduler::GetCurrentTime (TimeValue& rCurrentTime)
405cdf0e10cSrcweir {
406cdf0e10cSrcweir     TimeValue aSystemTime;
407cdf0e10cSrcweir     if (osl_getSystemTime(&aSystemTime))
408cdf0e10cSrcweir         return osl_getLocalTimeFromSystemTime(&aSystemTime, &rCurrentTime);
409cdf0e10cSrcweir     return false;
410cdf0e10cSrcweir }
411cdf0e10cSrcweir 
412cdf0e10cSrcweir 
413cdf0e10cSrcweir 
414cdf0e10cSrcweir 
GetTimeDifference(const TimeValue & rTargetTime,const TimeValue & rCurrentTime)415cdf0e10cSrcweir sal_Int64 TimerScheduler::GetTimeDifference (
416cdf0e10cSrcweir     const TimeValue& rTargetTime,
417cdf0e10cSrcweir     const TimeValue& rCurrentTime)
418cdf0e10cSrcweir {
419cdf0e10cSrcweir     return ConvertFromTimeValue(rTargetTime) - ConvertFromTimeValue(rCurrentTime);
420cdf0e10cSrcweir }
421cdf0e10cSrcweir 
422cdf0e10cSrcweir 
423cdf0e10cSrcweir 
424cdf0e10cSrcweir 
ConvertToTimeValue(TimeValue & rTimeValue,const sal_Int64 nTimeDifference)425cdf0e10cSrcweir void TimerScheduler::ConvertToTimeValue (
426cdf0e10cSrcweir     TimeValue& rTimeValue,
427cdf0e10cSrcweir     const sal_Int64 nTimeDifference)
428cdf0e10cSrcweir {
429cdf0e10cSrcweir     rTimeValue.Seconds = sal::static_int_cast<sal_Int32>(nTimeDifference / 1000000000L);
430cdf0e10cSrcweir     rTimeValue.Nanosec = sal::static_int_cast<sal_Int32>(nTimeDifference % 1000000000L);
431cdf0e10cSrcweir }
432cdf0e10cSrcweir 
433cdf0e10cSrcweir 
434cdf0e10cSrcweir 
435cdf0e10cSrcweir 
ConvertFromTimeValue(const TimeValue & rTimeValue)436cdf0e10cSrcweir sal_Int64 TimerScheduler::ConvertFromTimeValue (
437cdf0e10cSrcweir     const TimeValue& rTimeValue)
438cdf0e10cSrcweir {
439cdf0e10cSrcweir     return sal_Int64(rTimeValue.Seconds) * 1000000000L + rTimeValue.Nanosec;
440cdf0e10cSrcweir }
441cdf0e10cSrcweir 
442cdf0e10cSrcweir 
443cdf0e10cSrcweir 
444cdf0e10cSrcweir 
445cdf0e10cSrcweir //===== TimerTask =============================================================
446cdf0e10cSrcweir 
447cdf0e10cSrcweir namespace {
448cdf0e10cSrcweir 
TimerTask(const PresenterTimer::Task & rTask,const TimeValue & rDueTime,const sal_Int64 nRepeatIntervall,const sal_Int32 nTaskId)449cdf0e10cSrcweir TimerTask::TimerTask (
450cdf0e10cSrcweir     const PresenterTimer::Task& rTask,
451cdf0e10cSrcweir     const TimeValue& rDueTime,
452cdf0e10cSrcweir     const sal_Int64 nRepeatIntervall,
453cdf0e10cSrcweir     const sal_Int32 nTaskId)
454cdf0e10cSrcweir     : maTask(rTask),
455cdf0e10cSrcweir       maDueTime(rDueTime),
456cdf0e10cSrcweir       mnRepeatIntervall(nRepeatIntervall),
457cdf0e10cSrcweir       mnTaskId(nTaskId),
458cdf0e10cSrcweir       mbIsCanceled(false)
459cdf0e10cSrcweir {
460cdf0e10cSrcweir }
461cdf0e10cSrcweir 
462cdf0e10cSrcweir } // end of anonymous namespace
463cdf0e10cSrcweir 
464cdf0e10cSrcweir 
465cdf0e10cSrcweir 
466cdf0e10cSrcweir 
467cdf0e10cSrcweir //===== PresenterTimer ========================================================
468cdf0e10cSrcweir 
469cdf0e10cSrcweir 
470cdf0e10cSrcweir ::rtl::Reference<PresenterClockTimer> PresenterClockTimer::mpInstance;
471cdf0e10cSrcweir 
Instance(const css::uno::Reference<css::uno::XComponentContext> & rxContext)472cdf0e10cSrcweir ::rtl::Reference<PresenterClockTimer> PresenterClockTimer::Instance (
473cdf0e10cSrcweir     const css::uno::Reference<css::uno::XComponentContext>& rxContext)
474cdf0e10cSrcweir {
475cdf0e10cSrcweir     ::osl::MutexGuard aSolarGuard (::osl::Mutex::getGlobalMutex());
476cdf0e10cSrcweir 
477cdf0e10cSrcweir     ::rtl::Reference<PresenterClockTimer> pTimer;
478cdf0e10cSrcweir     if (mpInstance.is())
479cdf0e10cSrcweir     {
480cdf0e10cSrcweir         pTimer = mpInstance;
481cdf0e10cSrcweir     }
482cdf0e10cSrcweir     if ( ! pTimer.is())
483cdf0e10cSrcweir     {
484cdf0e10cSrcweir         pTimer = ::rtl::Reference<PresenterClockTimer>(new PresenterClockTimer(rxContext));
485cdf0e10cSrcweir         mpInstance = pTimer;
486cdf0e10cSrcweir     }
487cdf0e10cSrcweir     return pTimer;
488cdf0e10cSrcweir }
489cdf0e10cSrcweir 
490cdf0e10cSrcweir 
491cdf0e10cSrcweir 
492cdf0e10cSrcweir 
PresenterClockTimer(const Reference<XComponentContext> & rxContext)493cdf0e10cSrcweir PresenterClockTimer::PresenterClockTimer (const Reference<XComponentContext>& rxContext)
494cdf0e10cSrcweir     : PresenterClockTimerInterfaceBase(m_aMutex),
495cdf0e10cSrcweir       maListeners(),
496cdf0e10cSrcweir       maDateTime(),
497cdf0e10cSrcweir       mnTimerTaskId(PresenterTimer::NotAValidTaskId),
498cdf0e10cSrcweir       mbIsCallbackPending(false),
499cdf0e10cSrcweir       mxRequestCallback()
500cdf0e10cSrcweir {
501cdf0e10cSrcweir     Reference<lang::XMultiComponentFactory> xFactory (
502cdf0e10cSrcweir         rxContext->getServiceManager(), UNO_QUERY);
503cdf0e10cSrcweir     if (xFactory.is())
504cdf0e10cSrcweir         mxRequestCallback = Reference<awt::XRequestCallback>(
505cdf0e10cSrcweir             xFactory->createInstanceWithContext(
506cdf0e10cSrcweir                 A2S("com.sun.star.awt.AsyncCallback"),
507cdf0e10cSrcweir                 rxContext),
508cdf0e10cSrcweir             UNO_QUERY_THROW);
509cdf0e10cSrcweir }
510cdf0e10cSrcweir 
511cdf0e10cSrcweir 
512cdf0e10cSrcweir 
513cdf0e10cSrcweir 
~PresenterClockTimer(void)514cdf0e10cSrcweir PresenterClockTimer::~PresenterClockTimer (void)
515cdf0e10cSrcweir {
516cdf0e10cSrcweir     if (mnTimerTaskId != PresenterTimer::NotAValidTaskId)
517cdf0e10cSrcweir     {
518cdf0e10cSrcweir         PresenterTimer::CancelTask(mnTimerTaskId);
519cdf0e10cSrcweir         mnTimerTaskId = PresenterTimer::NotAValidTaskId;
520cdf0e10cSrcweir     }
521cdf0e10cSrcweir 
522cdf0e10cSrcweir     Reference<lang::XComponent> xComponent (mxRequestCallback, UNO_QUERY);
523cdf0e10cSrcweir     if (xComponent.is())
524cdf0e10cSrcweir         xComponent->dispose();
525cdf0e10cSrcweir     mxRequestCallback = NULL;
526cdf0e10cSrcweir }
527cdf0e10cSrcweir 
528cdf0e10cSrcweir 
529cdf0e10cSrcweir 
530cdf0e10cSrcweir 
AddListener(const SharedListener & rListener)531cdf0e10cSrcweir void PresenterClockTimer::AddListener (const SharedListener& rListener)
532cdf0e10cSrcweir {
533cdf0e10cSrcweir     osl::MutexGuard aGuard (maMutex);
534cdf0e10cSrcweir 
535cdf0e10cSrcweir     maListeners.push_back(rListener);
536cdf0e10cSrcweir 
537cdf0e10cSrcweir     // Create a timer task when the first listener is added.
538cdf0e10cSrcweir     if (mnTimerTaskId==PresenterTimer::NotAValidTaskId)
539cdf0e10cSrcweir     {
540cdf0e10cSrcweir         mnTimerTaskId = PresenterTimer::ScheduleRepeatedTask(
541cdf0e10cSrcweir             ::boost::bind(&PresenterClockTimer::CheckCurrentTime, this, _1),
542cdf0e10cSrcweir             0,
543cdf0e10cSrcweir             250000000 /*ns*/);
544cdf0e10cSrcweir     }
545cdf0e10cSrcweir }
546cdf0e10cSrcweir 
547cdf0e10cSrcweir 
548cdf0e10cSrcweir 
549cdf0e10cSrcweir 
RemoveListener(const SharedListener & rListener)550cdf0e10cSrcweir void PresenterClockTimer::RemoveListener (const SharedListener& rListener)
551cdf0e10cSrcweir {
552cdf0e10cSrcweir     osl::MutexGuard aGuard (maMutex);
553cdf0e10cSrcweir 
554cdf0e10cSrcweir     ListenerContainer::iterator iListener (::std::find(
555cdf0e10cSrcweir         maListeners.begin(),
556cdf0e10cSrcweir         maListeners.end(),
557cdf0e10cSrcweir         rListener));
558cdf0e10cSrcweir     if (iListener != maListeners.end())
559cdf0e10cSrcweir         maListeners.erase(iListener);
560cdf0e10cSrcweir     if (maListeners.size() == 0)
561cdf0e10cSrcweir     {
562cdf0e10cSrcweir         // We have no more clients and therefore are not interested in time changes.
563cdf0e10cSrcweir         if (mnTimerTaskId != PresenterTimer::NotAValidTaskId)
564cdf0e10cSrcweir         {
565cdf0e10cSrcweir             PresenterTimer::CancelTask(mnTimerTaskId);
566cdf0e10cSrcweir             mnTimerTaskId = PresenterTimer::NotAValidTaskId;
567cdf0e10cSrcweir         }
568cdf0e10cSrcweir         mpInstance = NULL;
569cdf0e10cSrcweir     }
570cdf0e10cSrcweir }
571cdf0e10cSrcweir 
572cdf0e10cSrcweir 
573cdf0e10cSrcweir 
574cdf0e10cSrcweir 
GetCurrentTime(void)575cdf0e10cSrcweir oslDateTime PresenterClockTimer::GetCurrentTime (void)
576cdf0e10cSrcweir {
577cdf0e10cSrcweir     TimeValue aCurrentTime;
578cdf0e10cSrcweir     TimerScheduler::GetCurrentTime(aCurrentTime);
579cdf0e10cSrcweir     oslDateTime aDateTime;
580cdf0e10cSrcweir     osl_getDateTimeFromTimeValue(&aCurrentTime, &aDateTime);
581cdf0e10cSrcweir     return aDateTime;
582cdf0e10cSrcweir }
583cdf0e10cSrcweir 
584cdf0e10cSrcweir 
585cdf0e10cSrcweir 
586cdf0e10cSrcweir 
GetTimeDifference(const oslDateTime & rNow,const oslDateTime & rThen)587cdf0e10cSrcweir sal_Int64 PresenterClockTimer::GetTimeDifference (
588cdf0e10cSrcweir     const oslDateTime& rNow,
589cdf0e10cSrcweir     const oslDateTime& rThen)
590cdf0e10cSrcweir {
591cdf0e10cSrcweir     TimeValue aNow;
592cdf0e10cSrcweir     TimeValue aThen;
593cdf0e10cSrcweir     if (osl_getTimeValueFromDateTime(const_cast<oslDateTime*>(&rNow),&aNow)
594cdf0e10cSrcweir         && osl_getTimeValueFromDateTime(const_cast<oslDateTime*>(&rThen),&aThen))
595cdf0e10cSrcweir     {
596cdf0e10cSrcweir         return TimerScheduler::GetTimeDifference(aNow, aThen);
597cdf0e10cSrcweir     }
598cdf0e10cSrcweir     else
599cdf0e10cSrcweir         return -1;
600cdf0e10cSrcweir }
601cdf0e10cSrcweir 
602cdf0e10cSrcweir 
603cdf0e10cSrcweir 
604cdf0e10cSrcweir 
CheckCurrentTime(const TimeValue & rCurrentTime)605cdf0e10cSrcweir void PresenterClockTimer::CheckCurrentTime (const TimeValue& rCurrentTime)
606cdf0e10cSrcweir {
607cdf0e10cSrcweir     css::uno::Reference<css::awt::XRequestCallback> xRequestCallback;
608cdf0e10cSrcweir     css::uno::Reference<css::awt::XCallback> xCallback;
609cdf0e10cSrcweir     {
610cdf0e10cSrcweir         osl::MutexGuard aGuard (maMutex);
611cdf0e10cSrcweir 
612cdf0e10cSrcweir         TimeValue aCurrentTime (rCurrentTime);
613cdf0e10cSrcweir         oslDateTime aDateTime;
614cdf0e10cSrcweir         if (osl_getDateTimeFromTimeValue(&aCurrentTime, &aDateTime))
615cdf0e10cSrcweir         {
616cdf0e10cSrcweir             if (aDateTime.Seconds != maDateTime.Seconds
617cdf0e10cSrcweir                 || aDateTime.Minutes != maDateTime.Minutes
618cdf0e10cSrcweir                 || aDateTime.Seconds != maDateTime.Seconds)
619cdf0e10cSrcweir             {
620cdf0e10cSrcweir                 // The displayed part of the current time has changed.
621cdf0e10cSrcweir                 // Prepare to call the listeners.
622cdf0e10cSrcweir                 maDateTime = aDateTime;
623cdf0e10cSrcweir 
624cdf0e10cSrcweir                 // Schedule notification of listeners.
625cdf0e10cSrcweir                 if (mxRequestCallback.is() && ! mbIsCallbackPending)
626cdf0e10cSrcweir                 {
627cdf0e10cSrcweir                     mbIsCallbackPending = true;
628cdf0e10cSrcweir                     xRequestCallback = mxRequestCallback;
629cdf0e10cSrcweir                     xCallback = this;
630cdf0e10cSrcweir                 }
631cdf0e10cSrcweir             }
632cdf0e10cSrcweir         }
633cdf0e10cSrcweir     }
634cdf0e10cSrcweir     if (mxRequestCallback.is() && xCallback.is())
635cdf0e10cSrcweir         xRequestCallback->addCallback(xCallback, Any());
636cdf0e10cSrcweir }
637cdf0e10cSrcweir 
638cdf0e10cSrcweir 
639cdf0e10cSrcweir 
640cdf0e10cSrcweir 
641cdf0e10cSrcweir //----- XCallback -------------------------------------------------------------
642cdf0e10cSrcweir 
notify(const css::uno::Any & rUserData)643cdf0e10cSrcweir void SAL_CALL PresenterClockTimer::notify (const css::uno::Any& rUserData)
644cdf0e10cSrcweir     throw (css::uno::RuntimeException)
645cdf0e10cSrcweir {
646cdf0e10cSrcweir     (void)rUserData;
647cdf0e10cSrcweir 
648cdf0e10cSrcweir     ListenerContainer aListenerCopy (maListeners);
649cdf0e10cSrcweir 
650cdf0e10cSrcweir     {
651cdf0e10cSrcweir         osl::MutexGuard aGuard (maMutex);
652cdf0e10cSrcweir 
653cdf0e10cSrcweir         mbIsCallbackPending = false;
654cdf0e10cSrcweir 
655cdf0e10cSrcweir         ::std::copy(
656cdf0e10cSrcweir             maListeners.begin(),
657cdf0e10cSrcweir             maListeners.end(),
658cdf0e10cSrcweir             ::std::back_inserter(aListenerCopy));
659cdf0e10cSrcweir     }
660cdf0e10cSrcweir 
661cdf0e10cSrcweir     if (aListenerCopy.size() > 0)
662cdf0e10cSrcweir     {
663cdf0e10cSrcweir         ListenerContainer::const_iterator iListener;
664cdf0e10cSrcweir         ListenerContainer::const_iterator iEnd (aListenerCopy.end());
665cdf0e10cSrcweir         for (iListener=aListenerCopy.begin(); iListener!=iEnd; ++iListener)
666cdf0e10cSrcweir         {
667cdf0e10cSrcweir             (*iListener)->TimeHasChanged(maDateTime);
668cdf0e10cSrcweir         }
669cdf0e10cSrcweir     }
670cdf0e10cSrcweir }
671cdf0e10cSrcweir 
672cdf0e10cSrcweir 
673cdf0e10cSrcweir 
674cdf0e10cSrcweir } } // end of namespace ::sdext::presenter
675