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