sync with tizen_2.0
[platform/framework/native/appfw.git] / src / system / FSys_VibratorImpl.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18 /**
19  * @file                FSys_VibratorImpl.cpp
20  * @brief               This is the implementation file for _VibratorImpl class.
21  */
22
23 #include <new>
24 #include <devman_haptic.h>
25
26 #include <FBaseSysLog.h>
27 #include <FBaseResult.h>
28 #include <FSysVibrator.h>
29
30 #include <FSys_VibratorImpl.h>
31
32 namespace Tizen { namespace System
33 {
34 namespace
35 {
36 static const haptic_dev_idx INDEX_SYSTEM_VIBRATOR = DEV_IDX_ALL;
37 static const unsigned int MODE_SYSTEM_VIBRATION = 0;
38 static const int LEVEL_SYSTEM_VIBRATION = -1;
39 static const long INVALID_PERIOD = 0L;
40 static const int INVALID_COUNT = -1;
41 static const int INVALID_LEVEL = -1;
42
43 inline bool
44 IsNegative(const int value)
45 {
46         return value < 0;
47 }
48
49 template <typename T> inline bool
50 IsCreated(const T* pT)
51 {
52         return pT != null;
53 }
54
55 template <typename T> inline void
56 SafeDelete(T*& rpT)
57 {
58         if (IsCreated(rpT))
59         {
60                 delete rpT;
61                 rpT = null;
62         }
63 }
64
65 result
66 InitializeVibrator(Handle& handle)
67 {
68         result r = E_SUCCESS;
69
70         Handle deviceHandle = device_haptic_open(INDEX_SYSTEM_VIBRATOR, MODE_SYSTEM_VIBRATION);
71         if (IsNegative(deviceHandle))
72         {
73                 SysAssertf(false, "device_haptic_open() failed. [index:%d, mode:%d, result:%d]", INDEX_SYSTEM_VIBRATOR, MODE_SYSTEM_VIBRATION, deviceHandle);
74
75                 r = E_SYSTEM;
76                 SysLogException(NID_SYS, r, "[%s] Vibrator initialize operation has failed. [result:%d]", GetErrorMessage(r), deviceHandle);
77                 return r;
78         }
79
80         handle = deviceHandle;
81
82         return r;
83 }
84
85 result
86 FinalizeVibrator(Handle& handle)
87 {
88         result r = E_SUCCESS;
89
90         if (handle != INVALID_HANDLE)
91         {
92                 int deviceResult = device_haptic_close(handle);
93                 if (IsNegative(deviceResult))
94                 {
95                         SysAssertf(false, "device_haptic_close() failed. [handle:%d, result:%d]", handle, deviceResult);
96
97                         r = E_SYSTEM;
98                         SysLogException(NID_SYS, r, "[%s] Vibrator finalize operation has failed. [result:%d]", GetErrorMessage(r), deviceResult);
99                         return r;
100                 }
101
102                 handle = INVALID_HANDLE;
103         }
104
105         return r;
106 }
107
108 result
109 StartVibration(const Handle handle, const long onPeriod, const int level)
110 {
111         result r = E_SUCCESS;
112         int aLevel = (level == 0) ? LEVEL_SYSTEM_VIBRATION : level;
113         SysLog(NID_SYS, "Vibrator Action level: %d", aLevel);
114
115         int deviceResult = device_haptic_play_monotone_with_detail_feedback_level(handle, onPeriod, (level == 0) ? LEVEL_SYSTEM_VIBRATION : level);
116         if (IsNegative(deviceResult))
117         {
118                 SysAssertf(false, "device_haptic_play_monotone_with_detail_feedback_level() failed. [handle:%d, duration:%ld, level:%d, result:%d]", handle, onPeriod, level, deviceResult);
119
120                 r = E_SYSTEM;
121                 SysLogException(NID_SYS, r, "[%s] Vibration start operation has failed. [handle:%d, duration:%ld, level:%d, result:%d]", GetErrorMessage(r), handle, onPeriod, level, deviceResult);
122                 return r;
123         }
124
125         return r;
126 }
127
128 result
129 StopVibration(const Handle handle)
130 {
131         result r = E_SUCCESS;
132
133         int deviceResult = device_haptic_stop_play(handle);
134         if (IsNegative(deviceResult))
135         {
136                 SysAssertf(false, "device_haptic_stop_play() failed. [handle:%d, result:%d]", handle, deviceResult);
137
138                 r = E_SYSTEM;
139                 SysLogException(NID_SYS, r, "[%s] Vibration stop operation has failed. [handle:%d, result:%d]", GetErrorMessage(r), handle, deviceResult);
140                 return r;
141         }
142
143         return r;
144 }
145 } // Anonymous
146
147
148 const _VibratorImpl::VibrationInformation _VibratorImpl::__INVALID_VIBRATION_INFORMATION = {
149         INVALID_PERIOD, // on period
150         INVALID_PERIOD, // off period
151         INVALID_COUNT,  // count
152         INVALID_LEVEL,  // level
153         false,          // is vibrating?
154         true,           // is finished?
155 };
156
157 _VibratorImpl::_VibratorImpl(void)
158         : __handle(INVALID_HANDLE)
159         , __pTimer(null)
160         , __vibrationInformation(_VibratorImpl::__INVALID_VIBRATION_INFORMATION)
161 {
162
163 }
164
165 _VibratorImpl::~_VibratorImpl(void)
166 {
167         Destruct();
168 }
169
170 result
171 _VibratorImpl::Construct(void)
172 {
173         SysAssertf(__handle == INVALID_HANDLE, "_VibratorImpl was already constructed. [handle:%d]", __handle);
174
175
176         result r = E_SUCCESS;
177
178         Tizen::Base::Runtime::Timer* pTimer = new (std::nothrow) Tizen::Base::Runtime::Timer();
179         if (!IsCreated(pTimer))
180         {
181                 r = E_OUT_OF_MEMORY;
182                 SysLogException(NID_SYS, r, "[%s] Timer allocation failed.", GetErrorMessage(r));
183                 return r;
184         }
185
186         r = pTimer->Construct(*this);
187         if (IsFailed(r))
188         {
189                 SafeDelete(pTimer);
190                 return r;
191         }
192
193         r = InitializeVibrator(__handle);
194         if (IsFailed(r))
195         {
196                 SafeDelete(pTimer);
197                 return r;
198         }
199
200         __pTimer = pTimer;
201
202         return r;
203 }
204
205 void
206 _VibratorImpl::Destruct(void)
207 {
208         if (!__vibrationInformation.isFinished)
209         {
210                 Stop();
211         }
212
213         SafeDelete(__pTimer);
214
215         if (__handle != INVALID_HANDLE)
216         {
217                 FinalizeVibrator(__handle);
218         }
219 }
220
221 result
222 _VibratorImpl::Start(long onPeriod, long offPeriod, int count, int level)
223 {
224         SysAssertf(__handle != INVALID_HANDLE, "_VibratorImpl was not constructed.");
225
226
227         // If (is vibrating)
228         //     Stop current vibration immediately
229         //
230         // Prepare vibration information
231         //
232         // Start vibration(=> This vibration just one repeat)
233         //
234         // Start repetition timer(=> Remaining vibration be started by timer)
235         //
236         // Modify vibration information
237         result r = E_SUCCESS;
238
239         if (!__vibrationInformation.isFinished)
240         {
241                 r = Stop();
242                 if (IsFailed(r))
243                 {
244                         return r;
245                 }
246
247                 __vibrationInformation = _VibratorImpl::__INVALID_VIBRATION_INFORMATION;
248         }
249
250         __vibrationInformation.onPeriod = onPeriod;
251         __vibrationInformation.offPeriod = offPeriod;
252         __vibrationInformation.count = count;
253         __vibrationInformation.level = level;
254
255         r = StartVibration(__handle, __vibrationInformation.onPeriod, __vibrationInformation.level);
256         if (IsFailed(r))
257         {
258                 __vibrationInformation = _VibratorImpl::__INVALID_VIBRATION_INFORMATION;
259                 return r;
260         }
261
262         r = __pTimer->Start(__vibrationInformation.onPeriod);
263         if (IsFailed(r))
264         {
265                 r = E_DEVICE_FAILED;
266                 SysLogException(NID_SYS, r, "[%s] Repetition timer starting failed.", GetErrorMessage(r));
267                 StopVibration(__handle);
268                 __vibrationInformation = _VibratorImpl::__INVALID_VIBRATION_INFORMATION;
269                 return r;
270         }
271
272         __vibrationInformation.isVibrating = true;
273         __vibrationInformation.isFinished = false;
274         __vibrationInformation.count--;
275
276         return r;
277 }
278
279 result
280 _VibratorImpl::Stop(void)
281 {
282         SysAssertf(__handle != INVALID_HANDLE, "_VibratorImpl was not constructed.");
283
284
285         // If (is not vibrating)
286         // {
287         //     return
288         // }
289         //
290         // Cancel timer(=> for block another repetition)
291         //
292         // Stop current vibration
293         //
294         // Initialize vibration information
295         result r = E_SUCCESS;
296
297         if (__vibrationInformation.isFinished)
298         {
299                 r = E_DEVICE_FAILED;
300                 SysLogException(NID_SYS, r, "[%s] Vibrator was already stopped.", GetErrorMessage(r));
301                 return r;
302         }
303
304         r = __pTimer->Cancel();
305         SysTryLog(NID_SYS, !IsFailed(r), "[%s] This canceling started just after timer has expired.", GetErrorMessage(r));
306
307         r = StopVibration(__handle);
308         if (IsFailed(r))
309         {
310                 return r;
311         }
312
313         __vibrationInformation = _VibratorImpl::__INVALID_VIBRATION_INFORMATION;
314
315         return r;
316 }
317
318 _VibratorImpl*
319 _VibratorImpl::GetInstance(Vibrator& vibrator)
320 {
321         return vibrator.__pVibratorImpl;
322 }
323
324 const _VibratorImpl*
325 _VibratorImpl::GetInstance(const Vibrator& vibrator)
326 {
327         return vibrator.__pVibratorImpl;
328 }
329
330 void
331 _VibratorImpl::OnTimerExpired(Tizen::Base::Runtime::Timer& timer)
332 {
333         // If (is end of repetition)
334         // {
335         //     Initialize vibration information
336         //     return
337         // }
338         //
339         // If (is end of vibration)
340         // {
341         //     Start waiting
342         //     return
343         // }
344         //
345         // If (is end of waiting)
346         // {
347         //     Start vibration
348         //     return
349         // }
350         if (__vibrationInformation.count == 0)
351         {
352                 __vibrationInformation = _VibratorImpl::__INVALID_VIBRATION_INFORMATION;
353                 return;
354         }
355
356
357         result r = E_SUCCESS;
358
359         if (__vibrationInformation.isVibrating)
360         {
361                 // off period
362                 __vibrationInformation.isVibrating = false;
363
364                 r = timer.Start(__vibrationInformation.offPeriod);
365                 if (IsFailed(r))
366                 {
367                         SysLog(NID_SYS, "Vibration waiting failed.");
368                         goto CATCH;
369                 }
370         }
371         else
372         {
373                 // on period
374                 r = StartVibration(__handle, __vibrationInformation.onPeriod, __vibrationInformation.level);
375                 if (IsFailed(r))
376                 {
377                         goto CATCH;
378                 }
379
380                 r = __pTimer->Start(__vibrationInformation.onPeriod);
381                 if (IsFailed(r))
382                 {
383                         SysLog(NID_SYS, "Vibration re-starting failed.");
384                         StopVibration(__handle);
385                         goto CATCH;
386                 }
387
388                 __vibrationInformation.isVibrating = true;
389                 __vibrationInformation.count--;
390         }
391
392         return;
393
394 CATCH:
395         SysLogException(NID_UIX, r, "[%s] Critical error occurred! Vibration was stopped.", GetErrorMessage(r));
396         __vibrationInformation = _VibratorImpl::__INVALID_VIBRATION_INFORMATION;
397 }
398
399 } } // Tizen::System