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