Merge branch 'devel/master' into tizen
[platform/core/uifw/dali-adaptor.git] / dali / internal / sensor / tizen / tilt-sensor-impl-tizen.cpp
1 /*
2  * Copyright (c) 2021 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/internal/sensor/common/tilt-sensor-factory.h>
20 #include <dali/internal/sensor/tizen/tilt-sensor-impl-tizen.h>
21
22 // EXTERNAL INCLUDES
23 #include <dali/devel-api/common/singleton-service.h>
24 #include <dali/integration-api/debug.h>
25 #include <dali/public-api/object/type-registry.h>
26 #include <cmath>
27
28 namespace // unnamed namespace
29 {
30 const char* const SIGNAL_TILTED = "tilted";
31
32 const float MAX_ORIENTATION_ROLL_VALUE  = 90.f;
33 const float MAX_ORIENTATION_PITCH_VALUE = 180.f;
34 const float MAX_ACCELEROMETER_VALUE     = 9.8f;
35
36 // Type Registration
37 Dali::BaseHandle Create()
38 {
39   return Dali::Internal::Adaptor::TiltSensorFactory::Get();
40 }
41
42 Dali::TypeRegistration typeRegistration(typeid(Dali::TiltSensor), typeid(Dali::BaseHandle), Create);
43
44 Dali::SignalConnectorType signalConnector1(typeRegistration, SIGNAL_TILTED, Dali::Internal::Adaptor::TiltSensor::DoConnectSignal);
45
46 } // unnamed namespace
47
48 namespace Dali
49 {
50 namespace Internal
51 {
52 namespace Adaptor
53 {
54 #ifdef SENSOR_ENABLED
55 static void sensor_changed_cb(sensor_h sensor, sensor_event_s* event, void* user_data)
56 {
57   TiltSensorTizen* tiltSensor = reinterpret_cast<TiltSensorTizen*>(user_data);
58
59   if(tiltSensor)
60   {
61     tiltSensor->Update(event);
62   }
63
64   return;
65 }
66
67 static std::string get_sensor_error_string(int errorValue)
68 {
69   std::string ret;
70
71   switch(errorValue)
72   {
73     case SENSOR_ERROR_IO_ERROR:
74       ret = "SENSOR_ERROR_IO_ERROR";
75       break;
76     case SENSOR_ERROR_INVALID_PARAMETER:
77       ret = "SENSOR_ERROR_INVALID_PARAMETER";
78       break;
79     case SENSOR_ERROR_NOT_SUPPORTED:
80       ret = "SENSOR_ERROR_NOT_SUPPORTED";
81       break;
82     case SENSOR_ERROR_PERMISSION_DENIED:
83       ret = "SENSOR_ERROR_PERMISSION_DENIED";
84       break;
85     case SENSOR_ERROR_OUT_OF_MEMORY:
86       ret = "SENSOR_ERROR_OUT_OF_MEMORY";
87       break;
88     case SENSOR_ERROR_NOT_NEED_CALIBRATION:
89       ret = "SENSOR_ERROR_NOT_NEED_CALIBRATION";
90       break;
91     case SENSOR_ERROR_OPERATION_FAILED:
92       ret = "SENSOR_ERROR_OPERATION_FAILED";
93       break;
94   }
95
96   return ret;
97 }
98 #endif
99
100 TiltSensorTizen* TiltSensorTizen::New()
101 {
102   return new TiltSensorTizen();
103 }
104
105 TiltSensorTizen::~TiltSensorTizen()
106 {
107   Disconnect();
108 }
109
110 bool TiltSensorTizen::Connect()
111 {
112 #ifdef SENSOR_ENABLED
113   if(mState != DISCONNECTED)
114   {
115     Stop();
116     Disconnect();
117   }
118
119   const int interval = 1000 / mFrequencyHertz;
120
121   int  ret         = 0;
122   bool isSupported = false;
123
124   // try to use Orientation sensor at first for less power consumption.
125   ret = sensor_is_supported(SENSOR_ORIENTATION, &isSupported);
126
127   if(ret < 0)
128   {
129     DALI_LOG_ERROR("sensor_is_supported() failed : %s\n", get_sensor_error_string(ret).c_str());
130     return false;
131   }
132
133   if(isSupported == true)
134   {
135     mSensorType = SENSOR_ORIENTATION;
136   }
137   else
138   {
139     DALI_LOG_ERROR("sensor does not support SENSOR_ORIENTATION\n");
140
141     ret = sensor_is_supported(SENSOR_ACCELEROMETER, &isSupported);
142
143     if(ret < 0)
144     {
145       DALI_LOG_ERROR("sensor_is_supported() failed : %s\n", get_sensor_error_string(ret).c_str());
146       return false;
147     }
148
149     if(isSupported == false)
150     {
151       DALI_LOG_ERROR("sensor does not support both SENSOR_ORIENTATION and SENSOR_ACCELEROMETER\n");
152       return false;
153     }
154
155     mSensorType = SENSOR_ACCELEROMETER;
156   }
157
158   ret = sensor_get_default_sensor(mSensorType, &mSensor); /* mSensor should not be deleted */
159
160   if(ret < 0)
161   {
162     DALI_LOG_ERROR("sensor_get_default_sensor() failed : %s\n", get_sensor_error_string(ret).c_str());
163     return false;
164   }
165
166   ret = sensor_create_listener(mSensor, &mSensorListener);
167
168   if(ret < 0)
169   {
170     DALI_LOG_ERROR("sensor_create_listener() failed : %s\n", get_sensor_error_string(ret).c_str());
171     return false;
172   }
173
174   sensor_listener_set_event_cb(mSensorListener, interval, sensor_changed_cb, this);
175   sensor_listener_set_interval(mSensorListener, interval);
176
177   sensor_listener_set_option(mSensorListener, SENSOR_OPTION_DEFAULT /* Not receive data when LCD is off and in power save mode */);
178
179   mState = CONNECTED;
180
181   return true;
182 #endif
183
184   return false;
185 }
186
187 void TiltSensorTizen::Disconnect()
188 {
189   if(mSensorListener)
190   {
191     if(mState == STARTED)
192     {
193       Stop();
194     }
195
196     if(mState == STOPPED || mState == CONNECTED)
197     {
198 #ifdef SENSOR_ENABLED
199       sensor_listener_unset_event_cb(mSensorListener);
200       sensor_listener_stop(mSensorListener);
201       sensor_destroy_listener(mSensorListener);
202 #endif
203       mSensor         = NULL;
204       mSensorListener = NULL;
205       mState          = DISCONNECTED;
206     }
207   }
208 }
209
210 bool TiltSensorTizen::Start()
211 {
212   if(mSensorListener && (mState == CONNECTED || mState == STOPPED))
213   {
214 #ifdef SENSOR_ENABLED
215     int ret = 0;
216     ret     = sensor_listener_start(mSensorListener);
217     if(ret != SENSOR_ERROR_NONE)
218     {
219       DALI_LOG_ERROR("sensor_listener_start() failed : %s\n", get_sensor_error_string(ret).c_str());
220       Disconnect();
221       return false;
222     }
223
224     mState = STARTED;
225     return true;
226 #endif
227   }
228   else
229   {
230     if(mState == STARTED)
231     {
232       DALI_LOG_ERROR("TiltSensor is already started. Current state [%d]\n", mState);
233     }
234     else
235     {
236       // mState is DISCONNECTED
237       DALI_LOG_ERROR("TiltSensor is disconnected. Current state [%d]\n", mState);
238     }
239     return false;
240   }
241   return false;
242 }
243
244 void TiltSensorTizen::Stop()
245 {
246 #ifdef SENSOR_ENABLED
247   if(mSensorListener && mState == STARTED)
248   {
249     sensor_listener_stop(mSensorListener);
250     mState = STOPPED;
251   }
252 #endif
253 }
254
255 bool TiltSensorTizen::IsStarted() const
256 {
257   return (mSensorListener && mState == STARTED);
258 }
259
260 float TiltSensorTizen::GetRoll() const
261 {
262   return mRoll;
263 }
264
265 float TiltSensorTizen::GetPitch() const
266 {
267   return mPitch;
268 }
269
270 Quaternion TiltSensorTizen::GetRotation() const
271 {
272   return mRotation;
273 }
274
275 TiltSensor::TiltedSignalType& TiltSensorTizen::TiltedSignal()
276 {
277   return mTiltedSignal;
278 }
279
280 void TiltSensorTizen::SetUpdateFrequency(float frequencyHertz)
281 {
282   DALI_ASSERT_ALWAYS(frequencyHertz > 0.0f && "Frequency must have a positive value");
283
284   if(fabsf(mFrequencyHertz - frequencyHertz) >= GetRangedEpsilon(mFrequencyHertz, frequencyHertz))
285   {
286     mFrequencyHertz = frequencyHertz;
287
288 #ifdef SENSOR_ENABLED
289     if(mSensorListener)
290     {
291       const int interval = 1000 / mFrequencyHertz;
292       sensor_listener_set_interval(mSensorListener, interval);
293     }
294 #endif
295   }
296 }
297
298 float TiltSensorTizen::GetUpdateFrequency() const
299 {
300   return mFrequencyHertz;
301 }
302
303 void TiltSensorTizen::SetRotationThreshold(Radian rotationThreshold)
304 {
305   mRotationThreshold = rotationThreshold;
306 }
307
308 Radian TiltSensorTizen::GetRotationThreshold() const
309 {
310   return mRotationThreshold;
311 }
312
313 bool TiltSensorTizen::DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor)
314 {
315   bool        connected(true);
316   TiltSensor* sensor = dynamic_cast<TiltSensor*>(object);
317
318   if(sensor && SIGNAL_TILTED == signalName)
319   {
320     sensor->TiltedSignal().Connect(tracker, functor);
321   }
322   else
323   {
324     // signalName does not match any signal
325     connected = false;
326   }
327
328   return connected;
329 }
330
331 TiltSensorTizen::TiltSensorTizen()
332 : mState(DISCONNECTED),
333   mFrequencyHertz(Dali::TiltSensor::DEFAULT_UPDATE_FREQUENCY),
334   mSensor(NULL),
335   mSensorListener(NULL),
336   mRoll(0.0f),
337   mPitch(0.0f),
338   mRotation(Radian(0.0f), Vector3::YAXIS),
339   mRotationThreshold(0.0f)
340 {
341   // connect sensor
342   Connect();
343 }
344
345 #ifdef SENSOR_ENABLED
346 void TiltSensorTizen::Update(sensor_event_s* event)
347 {
348   Radian     newRoll(0.0f);
349   Radian     newPitch(0.0f);
350   Quaternion newRotation;
351
352   if(mSensorType == SENSOR_ORIENTATION)
353   {
354     newRoll  = Clamp(float(event->values[2] / MAX_ORIENTATION_ROLL_VALUE) /* -90 < roll < 90 */, -1.0f /*min*/, 1.0f /*max*/);
355     newPitch = Clamp(float(event->values[1] / MAX_ORIENTATION_PITCH_VALUE) /* -180 < pitch < 180 */, -1.0f /*min*/, 1.0f /*max*/);
356   }
357   else if(mSensorType == SENSOR_ACCELEROMETER)
358   {
359     newRoll  = Clamp(float(event->values[0] / MAX_ACCELEROMETER_VALUE), -1.0f /*min*/, 1.0f /*max*/);
360     newPitch = Clamp(float(event->values[1] / MAX_ACCELEROMETER_VALUE), -1.0f /*min*/, 1.0f /*max*/);
361   }
362   else
363   {
364     DALI_LOG_ERROR("Invalid sensor type\n");
365     return;
366   }
367
368   newRotation = Quaternion(Radian(newRoll * Math::PI * -0.5f), Vector3::YAXIS) *
369                 Quaternion(Radian(newPitch * Math::PI * -0.5f), Vector3::XAXIS);
370
371   Radian angle(Quaternion::AngleBetween(newRotation, mRotation));
372
373   // If the change in value is more than the threshold then emit tilted signal.
374   if(angle >= mRotationThreshold)
375   {
376     mRoll     = newRoll;
377     mPitch    = newPitch;
378     mRotation = newRotation;
379
380     // emit signal
381     if(!mTiltedSignal.Empty())
382     {
383       Dali::TiltSensor handle(this);
384       mTiltedSignal.Emit(handle);
385     }
386   }
387 }
388 #endif // SENSOR_ENABLED
389
390 } // namespace Adaptor
391
392 } // namespace Internal
393
394 } // namespace Dali