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