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