58cf46d734454c0cb363603acba8076fe8cf471c
[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 || mState == STOPPED ) )
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 == STARTED )
251     {
252       DALI_LOG_ERROR("TiltSensor is already started. Current state [%d]\n", mState);
253     }
254     else
255     {
256       // mState is DISCONNECTED
257       DALI_LOG_ERROR("TiltSensor is disconnected. Current state [%d]\n", mState);
258     }
259     return false;
260   }
261   return false;
262 }
263
264 void TiltSensor::Stop()
265 {
266 #ifdef SENSOR_ENABLED
267   if(mSensorListener && mState == STARTED)
268   {
269     sensor_listener_stop( mSensorListener );
270     mState = STOPPED;
271   }
272 #endif
273 }
274
275 bool TiltSensor::IsStarted() const
276 {
277   return ( mSensorListener && mState == STARTED );
278 }
279
280 float TiltSensor::GetRoll() const
281 {
282   return mRoll;
283 }
284
285 float TiltSensor::GetPitch() const
286 {
287   return mPitch;
288 }
289
290 Quaternion TiltSensor::GetRotation() const
291 {
292   return mRotation;
293 }
294
295 TiltSensor::TiltedSignalType& TiltSensor::TiltedSignal()
296 {
297   return mTiltedSignal;
298 }
299
300 void TiltSensor::SetUpdateFrequency( float frequencyHertz )
301 {
302   DALI_ASSERT_ALWAYS( frequencyHertz > 0.0f && "Frequency must have a positive value" );
303
304   if ( fabsf(mFrequencyHertz - frequencyHertz) >= GetRangedEpsilon(mFrequencyHertz, frequencyHertz) )
305   {
306     mFrequencyHertz = frequencyHertz;
307
308 #ifdef SENSOR_ENABLED
309     if(mSensorListener)
310     {
311       const int interval = 1000/mFrequencyHertz;
312       sensor_listener_set_interval(mSensorListener, interval);
313     }
314 #endif
315   }
316 }
317
318 float TiltSensor::GetUpdateFrequency() const
319 {
320   return mFrequencyHertz;
321 }
322
323 void TiltSensor::SetRotationThreshold(Radian rotationThreshold)
324 {
325   mRotationThreshold = rotationThreshold;
326 }
327
328 Radian TiltSensor::GetRotationThreshold() const
329 {
330   return mRotationThreshold;
331 }
332
333 bool TiltSensor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
334 {
335   bool connected( true );
336   TiltSensor* sensor = dynamic_cast<TiltSensor*>( object );
337
338   if( sensor && SIGNAL_TILTED == signalName )
339   {
340     sensor->TiltedSignal().Connect( tracker, functor );
341   }
342   else
343   {
344     // signalName does not match any signal
345     connected = false;
346   }
347
348   return connected;
349 }
350
351 TiltSensor::TiltSensor()
352 : mState(DISCONNECTED),
353   mFrequencyHertz( Dali::TiltSensor::DEFAULT_UPDATE_FREQUENCY ),
354   mSensor( NULL ),
355   mSensorListener( NULL ),
356   mRoll( 0.0f ),
357   mPitch( 0.0f ),
358   mRotation( Radian(0.0f), Vector3::YAXIS ),
359   mRotationThreshold( 0.0f )
360 {
361   // connect sensor
362   Connect();
363 }
364
365 #ifdef SENSOR_ENABLED
366 void TiltSensor::Update(sensor_event_s *event)
367 {
368   Radian newRoll( 0.0f );
369   Radian newPitch( 0.0f );
370   Quaternion newRotation;
371
372   if(mSensorType == SENSOR_ORIENTATION)
373   {
374     newRoll  = Clamp( float(event->values[2]  / MAX_ORIENTATION_ROLL_VALUE)  /* -90 < roll < 90 */, -1.0f/*min*/, 1.0f/*max*/ );
375     newPitch = Clamp( float(event->values[1] / MAX_ORIENTATION_PITCH_VALUE) /* -180 < pitch < 180 */, -1.0f/*min*/, 1.0f/*max*/ );
376   }
377   else if(mSensorType == SENSOR_ACCELEROMETER)
378   {
379     newRoll  = Clamp( float(event->values[0] / MAX_ACCELEROMETER_VALUE), -1.0f/*min*/, 1.0f/*max*/ );
380     newPitch = Clamp( float(event->values[1] / MAX_ACCELEROMETER_VALUE), -1.0f/*min*/, 1.0f/*max*/ );
381   }
382   else
383   {
384     DALI_LOG_ERROR("Invalid sensor type\n");
385     return;
386   }
387
388   newRotation = Quaternion( Radian( newRoll * Math::PI * -0.5f ), Vector3::YAXIS ) *
389               Quaternion( Radian( newPitch * Math::PI * -0.5f ), Vector3::XAXIS );
390
391   Radian angle(Quaternion::AngleBetween(newRotation, mRotation));
392
393   // If the change in value is more than the threshold then emit tilted signal.
394   if( angle >= mRotationThreshold )
395   {
396     mRoll = newRoll;
397     mPitch = newPitch;
398     mRotation = newRotation;
399
400     // emit signal
401     if ( !mTiltedSignal.Empty() )
402     {
403       Dali::TiltSensor handle( this );
404       mTiltedSignal.Emit( handle );
405     }
406   }
407 }
408 #endif // SENSOR_ENABLED
409
410 } // namespace Adaptor
411
412 } // namespace Internal
413
414 } // namespace Dali