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