DALi Version 1.3.18
[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     sensor_is_supported(SENSOR_ACCELEROMETER, &isSupported);
147
148     if(isSupported == false)
149     {
150       DALI_LOG_ERROR("sensor does not support both SENSOR_ORIENTATION and SENSOR_ACCELEROMETER\n");
151       return false;
152     }
153
154     mSensorType = SENSOR_ACCELEROMETER;
155   }
156
157   ret = sensor_get_default_sensor(mSensorType, &mSensor); /* mSensor should not be deleted */
158
159   if(ret < 0)
160   {
161     DALI_LOG_ERROR("sensor_get_default_sensor() failed : %s\n", get_sensor_error_string(ret).c_str());
162     return false;
163   }
164
165   sensor_create_listener(mSensor, &mSensorListener);
166   sensor_listener_set_event_cb(mSensorListener, interval, sensor_changed_cb, this);
167   sensor_listener_set_interval(mSensorListener, interval);
168
169   sensor_listener_set_option(mSensorListener, SENSOR_OPTION_DEFAULT /* Not receive data when LCD is off and in power save mode */);
170
171   mState = CONNECTED;
172
173   return true;
174 #endif
175
176   return false;
177 }
178
179 void TiltSensorTizen::Disconnect()
180 {
181   if(mSensorListener)
182   {
183     if(mState == STARTED)
184     {
185       Stop();
186     }
187
188     if(mState == STOPPED || mState == CONNECTED)
189     {
190 #ifdef SENSOR_ENABLED
191       sensor_listener_unset_event_cb(mSensorListener);
192       sensor_listener_stop(mSensorListener);
193       sensor_destroy_listener(mSensorListener);
194 #endif
195       mSensor = NULL;
196       mSensorListener = NULL;
197       mState = DISCONNECTED;
198     }
199   }
200 }
201
202 bool TiltSensorTizen::Start()
203 {
204   if( mSensorListener && ( mState == CONNECTED || mState == STOPPED ) )
205   {
206 #ifdef SENSOR_ENABLED
207     int ret = 0;
208     ret = sensor_listener_start(mSensorListener);
209     if(ret != SENSOR_ERROR_NONE)
210     {
211       DALI_LOG_ERROR("sensor_listener_start() failed : %s\n", get_sensor_error_string(ret).c_str());
212       Disconnect();
213       return false;
214     }
215
216     mState = STARTED;
217     return true;
218 #endif
219   }
220   else
221   {
222     if( mState == STARTED )
223     {
224       DALI_LOG_ERROR("TiltSensor is already started. Current state [%d]\n", mState);
225     }
226     else
227     {
228       // mState is DISCONNECTED
229       DALI_LOG_ERROR("TiltSensor is disconnected. Current state [%d]\n", mState);
230     }
231     return false;
232   }
233   return false;
234 }
235
236 void TiltSensorTizen::Stop()
237 {
238 #ifdef SENSOR_ENABLED
239   if(mSensorListener && mState == STARTED)
240   {
241     sensor_listener_stop( mSensorListener );
242     mState = STOPPED;
243   }
244 #endif
245 }
246
247 bool TiltSensorTizen::IsStarted() const
248 {
249   return ( mSensorListener && mState == STARTED );
250 }
251
252 float TiltSensorTizen::GetRoll() const
253 {
254   return mRoll;
255 }
256
257 float TiltSensorTizen::GetPitch() const
258 {
259   return mPitch;
260 }
261
262 Quaternion TiltSensorTizen::GetRotation() const
263 {
264   return mRotation;
265 }
266
267 TiltSensor::TiltedSignalType& TiltSensorTizen::TiltedSignal()
268 {
269   return mTiltedSignal;
270 }
271
272 void TiltSensorTizen::SetUpdateFrequency( float frequencyHertz )
273 {
274   DALI_ASSERT_ALWAYS( frequencyHertz > 0.0f && "Frequency must have a positive value" );
275
276   if ( fabsf(mFrequencyHertz - frequencyHertz) >= GetRangedEpsilon(mFrequencyHertz, frequencyHertz) )
277   {
278     mFrequencyHertz = frequencyHertz;
279
280 #ifdef SENSOR_ENABLED
281     if(mSensorListener)
282     {
283       const int interval = 1000/mFrequencyHertz;
284       sensor_listener_set_interval(mSensorListener, interval);
285     }
286 #endif
287   }
288 }
289
290 float TiltSensorTizen::GetUpdateFrequency() const
291 {
292   return mFrequencyHertz;
293 }
294
295 void TiltSensorTizen::SetRotationThreshold(Radian rotationThreshold)
296 {
297   mRotationThreshold = rotationThreshold;
298 }
299
300 Radian TiltSensorTizen::GetRotationThreshold() const
301 {
302   return mRotationThreshold;
303 }
304
305 bool TiltSensorTizen::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
306 {
307   bool connected( true );
308   TiltSensor* sensor = dynamic_cast<TiltSensor*>( object );
309
310   if( sensor && SIGNAL_TILTED == signalName )
311   {
312     sensor->TiltedSignal().Connect( tracker, functor );
313   }
314   else
315   {
316     // signalName does not match any signal
317     connected = false;
318   }
319
320   return connected;
321 }
322
323 TiltSensorTizen::TiltSensorTizen()
324 : mState(DISCONNECTED),
325   mFrequencyHertz( Dali::TiltSensor::DEFAULT_UPDATE_FREQUENCY ),
326   mSensor( NULL ),
327   mSensorListener( NULL ),
328   mRoll( 0.0f ),
329   mPitch( 0.0f ),
330   mRotation( Radian(0.0f), Vector3::YAXIS ),
331   mRotationThreshold( 0.0f )
332 {
333   // connect sensor
334   Connect();
335 }
336
337 #ifdef SENSOR_ENABLED
338 void TiltSensorTizen::Update(sensor_event_s *event)
339 {
340   Radian newRoll( 0.0f );
341   Radian newPitch( 0.0f );
342   Quaternion newRotation;
343
344   if(mSensorType == SENSOR_ORIENTATION)
345   {
346     newRoll  = Clamp( float(event->values[2]  / MAX_ORIENTATION_ROLL_VALUE)  /* -90 < roll < 90 */, -1.0f/*min*/, 1.0f/*max*/ );
347     newPitch = Clamp( float(event->values[1] / MAX_ORIENTATION_PITCH_VALUE) /* -180 < pitch < 180 */, -1.0f/*min*/, 1.0f/*max*/ );
348   }
349   else if(mSensorType == SENSOR_ACCELEROMETER)
350   {
351     newRoll  = Clamp( float(event->values[0] / MAX_ACCELEROMETER_VALUE), -1.0f/*min*/, 1.0f/*max*/ );
352     newPitch = Clamp( float(event->values[1] / MAX_ACCELEROMETER_VALUE), -1.0f/*min*/, 1.0f/*max*/ );
353   }
354   else
355   {
356     DALI_LOG_ERROR("Invalid sensor type\n");
357     return;
358   }
359
360   newRotation = Quaternion( Radian( newRoll * Math::PI * -0.5f ), Vector3::YAXIS ) *
361               Quaternion( Radian( newPitch * Math::PI * -0.5f ), Vector3::XAXIS );
362
363   Radian angle(Quaternion::AngleBetween(newRotation, mRotation));
364
365   // If the change in value is more than the threshold then emit tilted signal.
366   if( angle >= mRotationThreshold )
367   {
368     mRoll = newRoll;
369     mPitch = newPitch;
370     mRotation = newRotation;
371
372     // emit signal
373     if ( !mTiltedSignal.Empty() )
374     {
375       Dali::TiltSensor handle( this );
376       mTiltedSignal.Emit( handle );
377     }
378   }
379 }
380 #endif // SENSOR_ENABLED
381
382 } // namespace Adaptor
383
384 } // namespace Internal
385
386 } // namespace Dali