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