* rotate.c: Fix a few bugs + don't use p_libvlc_global to store instance specific...
[vlc.git] / modules / control / motion.c
1 /*****************************************************************************
2  * motion.c: control VLC with laptop built-in motion sensors
3  *****************************************************************************
4  * Copyright (C) 2006 the VideoLAN team
5  * $Id$
6  *
7  * Author: Sam Hocevar <sam@zoy.org>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <stdlib.h>                                      /* malloc(), free() */
28 #include <string.h>
29
30 #include <vlc/vlc.h>
31 #include <vlc_interface.h>
32 #include <vlc_vout.h>
33
34 #ifdef HAVE_UNISTD_H
35 #    include <unistd.h>
36 #endif
37
38 /*****************************************************************************
39  * intf_sys_t: description and status of interface
40  *****************************************************************************/
41 struct intf_sys_t
42 {
43     enum { NO_SENSOR, HDAPS_SENSOR, AMS_SENSOR } sensor;
44
45     int i_calibrate;
46
47     vlc_bool_t b_use_rotate;
48 };
49
50 /*****************************************************************************
51  * Local prototypes.
52  *****************************************************************************/
53 static int  Open   ( vlc_object_t * );
54 static void Close  ( vlc_object_t * );
55
56 static void RunIntf( intf_thread_t *p_intf );
57 static int GetOrientation( intf_thread_t *p_intf );
58
59 #define USE_ROTATE_TEXT N_("Use the rotate video filter instead of transform")
60
61 /*****************************************************************************
62  * Module descriptor
63  *****************************************************************************/
64 vlc_module_begin();
65     set_shortname( _("motion"));
66     set_category( CAT_INTERFACE );
67     set_description( _("motion control interface") );
68
69     add_bool( "motion-use-rotate", 0, NULL,
70               USE_ROTATE_TEXT, USE_ROTATE_TEXT, VLC_FALSE );
71
72     set_capability( "interface", 0 );
73     set_callbacks( Open, Close );
74 vlc_module_end();
75
76 /*****************************************************************************
77  * OpenIntf: initialise interface
78  *****************************************************************************/
79 int Open ( vlc_object_t *p_this )
80 {
81     intf_thread_t *p_intf = (intf_thread_t *)p_this;
82     FILE *f;
83     int i_x, i_y;
84
85     p_intf->p_sys = malloc( sizeof( intf_sys_t ) );
86     if( p_intf->p_sys == NULL )
87     {
88         return VLC_ENOMEM;
89     }
90
91     if( access( "/sys/devices/platform/hdaps/position", R_OK ) == 0 )
92     {
93         /* IBM HDAPS support */
94         f = fopen( "/sys/devices/platform/hdaps/calibrate", "r" );
95         if( f )
96         {
97             i_x = i_y = 0;
98             fscanf( f, "(%d,%d)", &i_x, &i_y );
99             fclose( f );
100             p_intf->p_sys->i_calibrate = i_x;
101             p_intf->p_sys->sensor = HDAPS_SENSOR;
102         }
103         else
104         {
105             p_intf->p_sys->sensor = NO_SENSOR;
106         }
107     }
108     else if( access( "/sys/devices/ams/x", R_OK ) == 0 )
109     {
110         /* Apple Motion Sensor support */
111         p_intf->p_sys->sensor = AMS_SENSOR;
112     }
113     else
114     {
115         /* No motion sensor support */
116         p_intf->p_sys->sensor = NO_SENSOR;
117     }
118
119     p_intf->pf_run = RunIntf;
120
121     p_intf->p_sys->b_use_rotate = config_GetInt( p_intf, "motion-use-rotate" );
122
123     return VLC_SUCCESS;
124 }
125
126 /*****************************************************************************
127  * CloseIntf: destroy interface
128  *****************************************************************************/
129 void Close ( vlc_object_t *p_this )
130 {
131     intf_thread_t *p_intf = (intf_thread_t *)p_this;
132
133     free( p_intf->p_sys );
134 }
135
136 /*****************************************************************************
137  * RunIntf: main loop
138  *****************************************************************************/
139 static void RunIntf( intf_thread_t *p_intf )
140 {
141     int i_x, i_oldx = 0;
142
143     while( !intf_ShouldDie( p_intf ) )
144     {
145 #define LOW_THRESHOLD 80
146 #define HIGH_THRESHOLD 100
147         vout_thread_t *p_vout;
148         const char *psz_filter, *psz_type;
149         vlc_bool_t b_change = VLC_FALSE;
150
151         /* Wait a bit, get orientation, change filter if necessary */
152         msleep( INTF_IDLE_SLEEP );
153
154         i_x = GetOrientation( p_intf );
155
156         if( p_intf->p_sys->b_use_rotate )
157         {
158             if( i_oldx != i_x )
159             {
160                 /* TODO: cache object pointer */
161                 vlc_object_t *p_obj =
162                 vlc_object_find_name( p_intf->p_libvlc, "rotate", FIND_CHILD );
163                 if( p_obj )
164                 {
165                     var_SetInteger( p_obj, "rotate-angle",((360+i_x/2)%360) );
166                     i_oldx = i_x;
167                     vlc_object_release( p_obj );
168                 }
169             }
170             continue;
171         }
172
173         if( i_x < -HIGH_THRESHOLD && i_oldx > -LOW_THRESHOLD )
174         {
175             b_change = VLC_TRUE;
176             psz_filter = "transform";
177             psz_type = "270";
178         }
179         else if( ( i_x > -LOW_THRESHOLD && i_oldx < -HIGH_THRESHOLD )
180                  || ( i_x < LOW_THRESHOLD && i_oldx > HIGH_THRESHOLD ) )
181         {
182             b_change = VLC_TRUE;
183             psz_filter = "";
184             psz_type = "";
185         }
186         else if( i_x > HIGH_THRESHOLD && i_oldx < LOW_THRESHOLD )
187         {
188             b_change = VLC_TRUE;
189             psz_filter = "transform";
190             psz_type = "90";
191         }
192
193         if( !b_change )
194         {
195             continue;
196         }
197
198         p_vout = (vout_thread_t *)
199             vlc_object_find( p_intf, VLC_OBJECT_VOUT, FIND_ANYWHERE );
200         if( !p_vout )
201         {
202             continue;
203         }
204
205         config_PutPsz( p_vout, "transform-type", psz_type );
206         var_SetString( p_vout, "vout-filter", psz_filter );
207         vlc_object_release( p_vout );
208
209         i_oldx = i_x;
210     }
211 }
212
213 /*****************************************************************************
214  * GetOrientation: get laptop orientation, range -180 / +180
215  *****************************************************************************/
216 static int GetOrientation( intf_thread_t *p_intf )
217 {
218     FILE *f;
219     int i_x, i_y;
220
221     switch( p_intf->p_sys->sensor )
222     {
223     case HDAPS_SENSOR:
224         f = fopen( "/sys/devices/platform/hdaps/position", "r" );
225         if( !f )
226         {
227             return 0;
228         }
229
230         i_x = i_y = 0;
231         fscanf( f, "(%d,%d)", &i_x, &i_y );
232         fclose( f );
233
234         return i_x - p_intf->p_sys->i_calibrate;
235
236     case AMS_SENSOR:
237         f = fopen( "/sys/devices/ams/x", "r" );
238         if( !f )
239         {
240             return 0;
241         }
242
243         fscanf( f, "%d", &i_x);
244         fclose( f );
245
246         return - i_x * 3; /* FIXME: arbitrary */
247
248     default:
249         return 0;
250     }
251 }
252