d86c9cddef6b2ea80c4776621c82b841ddc75714
[platform/core/appfw/app-core.git] / src / appcore-rotation.c
1 /*
2  *  app-core
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>, Jaeho Lee <jaeho81.lee@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22
23 #include <errno.h>
24 #include <stdlib.h>
25 #include <unistd.h>
26
27 #include <sensor_internal.h>
28 #include <vconf.h>
29 #include <Ecore.h>
30 #include "appcore-internal.h"
31
32 struct rot_s {
33         int handle;
34         int (*callback) (void *event_info, enum appcore_rm, void *);
35         enum appcore_rm mode;
36         int lock;
37         void *cbdata;
38         int cb_set;
39         int sensord_started;
40
41         struct ui_wm_rotate* wm_rotate;
42 };
43 static struct rot_s rot;
44
45 struct rot_evt {
46         enum auto_rotation_state re;
47         enum appcore_rm rm;
48 };
49
50 static struct rot_evt re_to_rm[] = {
51         {
52                 AUTO_ROTATION_DEGREE_0,
53                 APPCORE_RM_PORTRAIT_NORMAL,
54         },
55         {
56                 AUTO_ROTATION_DEGREE_90,
57                 APPCORE_RM_LANDSCAPE_NORMAL,
58         },
59         {
60                 AUTO_ROTATION_DEGREE_180,
61                 APPCORE_RM_PORTRAIT_REVERSE,
62         },
63         {
64                 AUTO_ROTATION_DEGREE_270,
65                 APPCORE_RM_LANDSCAPE_REVERSE,
66         },
67 };
68
69 static enum appcore_rm __get_mode(sensor_data_t data)
70 {
71         int i;
72         int event;
73         enum appcore_rm m;
74
75         m = APPCORE_RM_UNKNOWN;
76         if (data.value_count > 0) {
77                 event = (int)data.values[0];
78         } else {
79                 _ERR("Failed to get sensor data");
80                 return -1;
81         }
82
83         for (i = 0; i < sizeof(re_to_rm) / sizeof(re_to_rm[0]); i++) {
84                 if (re_to_rm[i].re == event) {
85                         m = re_to_rm[i].rm;
86                         break;
87                 }
88         }
89
90         return m;
91 }
92
93 static void __changed_cb(sensor_t sensor, unsigned int event_type,
94                 sensor_data_t *data, void *user_data)
95 {
96         enum appcore_rm m;
97
98         if (rot.lock)
99                 return;
100
101         if (event_type != AUTO_ROTATION_CHANGE_STATE_EVENT) {
102                 errno = EINVAL;
103                 return;
104         }
105
106         m = __get_mode(*data);
107
108         _DBG("[APP %d] Rotation: %d -> %d", getpid(), rot.mode, m);
109
110         if (rot.callback) {
111                 if (rot.cb_set && rot.mode != m) {
112                         _DBG("[APP %d] Rotation: %d -> %d", getpid(), rot.mode, m);
113                         rot.callback((void *)&m, m, user_data);
114                         rot.mode = m;
115                 }
116         }
117 }
118
119 static void __lock_cb(keynode_t *node, void *data)
120 {
121         int r;
122         enum appcore_rm m;
123
124         rot.lock = !vconf_keynode_get_bool(node);
125
126         if (rot.lock) {
127                 m = APPCORE_RM_PORTRAIT_NORMAL;
128                 if (rot.mode != m) {
129                         rot.callback((void *)&m, m, data);
130                         rot.mode = m;
131                 }
132                 _DBG("[APP %d] Rotation locked", getpid());
133                 return;
134         }
135
136         _DBG("[APP %d] Rotation unlocked", getpid());
137         if (rot.callback) {
138                 if (rot.cb_set) {
139                         r = appcore_get_rotation_state(&m);
140                         _DBG("[APP %d] Rotmode prev %d -> curr %d", getpid(),
141                              rot.mode, m);
142                         if (!r && rot.mode != m) {
143                                 rot.callback((void *)&m, m, data);
144                                 rot.mode = m;
145                         }
146                 }
147         }
148 }
149
150 static void __add_rotlock(void *data)
151 {
152         int r;
153         int lock;
154
155         lock = 0;
156         r = vconf_get_bool(VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL, &lock);
157         if (r)
158                 _DBG("[APP %d] Rotation vconf get bool failed", getpid());
159
160         rot.lock = !lock;
161
162         vconf_notify_key_changed(VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL, __lock_cb,
163                                  data);
164 }
165
166 static void __del_rotlock(void)
167 {
168         vconf_ignore_key_changed(VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL, __lock_cb);
169         rot.lock = 0;
170 }
171
172 EXPORT_API int appcore_set_rotation_cb(int (*cb) (void *evnet_info, enum appcore_rm, void *),
173                                        void *data)
174 {
175         if (rot.wm_rotate)
176                 return rot.wm_rotate->set_rotation_cb(cb, data);
177         else {
178                 bool r;
179                 int handle;
180                 sensor_t sensor = sensord_get_sensor(AUTO_ROTATION_SENSOR);
181
182                 if (cb == NULL) {
183                         errno = EINVAL;
184                         return -1;
185                 }
186
187                 if (rot.callback != NULL) {
188                         errno = EALREADY;
189                         return -1;
190                 }
191
192                 handle = sensord_connect(sensor);
193                 if (handle < 0) {
194                         _ERR("sensord_connect failed: %d", handle);
195                         return -1;
196                 }
197
198                 r = sensord_register_event(handle, AUTO_ROTATION_CHANGE_STATE_EVENT,
199                                       SENSOR_INTERVAL_NORMAL, 0, __changed_cb, data);
200                 if (!r) {
201                         _ERR("sensord_register_event failed");
202                         sensord_disconnect(handle);
203                         return -1;
204                 }
205
206                 rot.cb_set = 1;
207                 rot.callback = cb;
208                 rot.cbdata = data;
209
210                 r = sensord_start(handle, 0);
211                 if (!r) {
212                         _ERR("sensord_start failed");
213                         r = sensord_unregister_event(handle, AUTO_ROTATION_CHANGE_STATE_EVENT);
214                         if (!r)
215                                 _ERR("sensord_unregister_event failed");
216
217                         rot.callback = NULL;
218                         rot.cbdata = NULL;
219                         rot.cb_set = 0;
220                         rot.sensord_started = 0;
221                         sensord_disconnect(handle);
222                         return -1;
223                 }
224                 rot.sensord_started = 1;
225
226                 rot.handle = handle;
227                 __add_rotlock(data);
228         }
229         return 0;
230 }
231
232 EXPORT_API int appcore_unset_rotation_cb(void)
233 {
234         if (rot.wm_rotate)
235                 return rot.wm_rotate->unset_rotation_cb();
236         else {
237                 bool r;
238
239                 _retv_if(rot.callback == NULL, 0);
240
241                 __del_rotlock();
242
243                 if (rot.cb_set) {
244                         r = sensord_unregister_event(rot.handle,
245                                                 AUTO_ROTATION_CHANGE_STATE_EVENT);
246                         if (!r) {
247                                 _ERR("sensord_unregister_event failed");
248                                 return -1;
249                         }
250                         rot.cb_set = 0;
251                 }
252                 rot.callback = NULL;
253                 rot.cbdata = NULL;
254
255                 if (rot.sensord_started == 1) {
256                         r = sensord_stop(rot.handle);
257                         if (!r) {
258                                 _ERR("sensord_stop failed");
259                                 return -1;
260                         }
261                         rot.sensord_started = 0;
262                 }
263
264                 r = sensord_disconnect(rot.handle);
265                 if (!r) {
266                         _ERR("sensord_disconnect failed");
267                         return -1;
268                 }
269                 rot.handle = -1;
270         }
271         return 0;
272 }
273
274 EXPORT_API int appcore_get_rotation_state(enum appcore_rm *curr)
275 {
276         if (rot.wm_rotate)
277                 return rot.wm_rotate->get_rotation_state(curr);
278         else {
279                 bool r;
280                 sensor_data_t data;
281
282                 if (curr == NULL) {
283                         errno = EINVAL;
284                         return -1;
285                 }
286
287                 r = sensord_get_data(rot.handle, AUTO_ROTATION_SENSOR, &data);
288                 if (!r) {
289                         _ERR("sensord_get_data failed");
290                         *curr = APPCORE_RM_UNKNOWN;
291                         return -1;
292                 }
293
294                 *curr = __get_mode(data);
295         }
296         return 0;
297 }
298
299 EXPORT_API int appcore_pause_rotation_cb(void)
300 {
301         if (rot.wm_rotate)
302                 return rot.wm_rotate->pause_rotation_cb();
303         else {
304                 bool r;
305
306                 _retv_if(rot.callback == NULL, 0);
307                 _DBG("[APP %d] appcore_pause_rotation_cb is called", getpid());
308
309                 __del_rotlock();
310
311                 if (rot.cb_set) {
312                         r = sensord_unregister_event(rot.handle,
313                                                 AUTO_ROTATION_CHANGE_STATE_EVENT);
314                         if (!r) {
315                                 _ERR("sensord_unregister_event failed");
316                                 return -1;
317                         }
318                         rot.cb_set = 0;
319                 }
320
321                 if (rot.sensord_started == 1) {
322                         r = sensord_stop(rot.handle);
323                         if (!r) {
324                                 _ERR("sensord_stop failed");
325                                 return -1;
326                         }
327                         rot.sensord_started = 0;
328                 }
329         }
330
331         return 0;
332 }
333
334 EXPORT_API int appcore_resume_rotation_cb(void)
335 {
336         if (rot.wm_rotate)
337                 return rot.wm_rotate->resume_rotation_cb();
338         else {
339                 bool r;
340                 enum appcore_rm m;
341
342                 _retv_if(rot.callback == NULL, 0);
343                 _DBG("[APP %d] appcore_resume_rotation_cb is called", getpid());
344
345                 if (rot.cb_set == 0) {
346                         r = sensord_register_event(rot.handle,
347                                         AUTO_ROTATION_CHANGE_STATE_EVENT,
348                                         SENSOR_INTERVAL_NORMAL, 0, __changed_cb, rot.cbdata);
349                         if (!r) {
350                                 _ERR("sensord_register_event failed");
351                                 return -1;
352                         }
353                         rot.cb_set = 1;
354                 }
355
356                 if (rot.sensord_started == 0) {
357                         r = sensord_start(rot.handle, 0);
358                         if (!r) {
359                                 _ERR("sensord_start failed");
360                                 r = sensord_unregister_event(rot.handle,
361                                                     AUTO_ROTATION_CHANGE_STATE_EVENT);
362                                 if (!r)
363                                         _ERR("sensord_unregister_event failed");
364                                 rot.cb_set = 0;
365                                 return -1;
366                         }
367                         rot.sensord_started = 1;
368                 }
369
370                 __add_rotlock(rot.cbdata);
371
372                 r = appcore_get_rotation_state(&m);
373                 _DBG("[APP %d] Rotmode prev %d -> curr %d", getpid(), rot.mode, m);
374                 if (!r && rot.mode != m && rot.lock == 0) {
375                         rot.callback((void *)&m, m, rot.cbdata);
376                         rot.mode = m;
377                 }
378         }
379         return 0;
380 }
381
382 EXPORT_API int appcore_set_wm_rotation(struct ui_wm_rotate* wm_rotate)
383 {
384         if (!wm_rotate) return -1;
385
386         if (rot.callback) {
387                 wm_rotate->set_rotation_cb(rot.callback, rot.cbdata);
388                 appcore_unset_rotation_cb();
389         }
390         rot.wm_rotate = wm_rotate;
391         _DBG("[APP %d] Support wm rotate:%p", getpid(), wm_rotate);
392         return 0;
393 }