98f53edcfe0c604a5edd6779cf02f62fc117b2ab
[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     if( p_intf->p_sys->b_use_rotate )
124     {
125         var_Create( p_intf->p_libvlc, "rotate_angle", VLC_VAR_INTEGER );
126     }
127
128     return VLC_SUCCESS;
129 }
130
131 /*****************************************************************************
132  * CloseIntf: destroy interface
133  *****************************************************************************/
134 void Close ( vlc_object_t *p_this )
135 {
136     intf_thread_t *p_intf = (intf_thread_t *)p_this;
137
138     free( p_intf->p_sys );
139 }
140
141 /*****************************************************************************
142  * RunIntf: main loop
143  *****************************************************************************/
144 static void RunIntf( intf_thread_t *p_intf )
145 {
146     int i_x, i_oldx = 0;
147
148     while( !intf_ShouldDie( p_intf ) )
149     {
150 #define LOW_THRESHOLD 80
151 #define HIGH_THRESHOLD 100
152         vout_thread_t *p_vout;
153         const char *psz_filter, *psz_type;
154         vlc_bool_t b_change = VLC_FALSE;
155
156         /* Wait a bit, get orientation, change filter if necessary */
157         msleep( INTF_IDLE_SLEEP );
158
159         i_x = GetOrientation( p_intf );
160
161         if( p_intf->p_sys->b_use_rotate )
162         {
163             if( i_oldx != i_x )
164             {
165                 var_SetInteger( p_intf->p_libvlc, "rotate_angle",
166                             ((360+i_x/2)%360) );
167                 i_oldx = i_x;
168             }
169             continue;
170         }
171
172         if( i_x < -HIGH_THRESHOLD && i_oldx > -LOW_THRESHOLD )
173         {
174             b_change = VLC_TRUE;
175             psz_filter = "transform";
176             psz_type = "270";
177         }
178         else if( ( i_x > -LOW_THRESHOLD && i_oldx < -HIGH_THRESHOLD )
179                  || ( i_x < LOW_THRESHOLD && i_oldx > HIGH_THRESHOLD ) )
180         {
181             b_change = VLC_TRUE;
182             psz_filter = "";
183             psz_type = "";
184         }
185         else if( i_x > HIGH_THRESHOLD && i_oldx < LOW_THRESHOLD )
186         {
187             b_change = VLC_TRUE;
188             psz_filter = "transform";
189             psz_type = "90";
190         }
191
192         if( !b_change )
193         {
194             continue;
195         }
196
197         p_vout = (vout_thread_t *)
198             vlc_object_find( p_intf, VLC_OBJECT_VOUT, FIND_ANYWHERE );
199         if( !p_vout )
200         {
201             continue;
202         }
203
204         config_PutPsz( p_vout, "transform-type", psz_type );
205         var_SetString( p_vout, "vout-filter", psz_filter );
206         vlc_object_release( p_vout );
207
208         i_oldx = i_x;
209     }
210 }
211
212 /*****************************************************************************
213  * GetOrientation: get laptop orientation, range -180 / +180
214  *****************************************************************************/
215 static int GetOrientation( intf_thread_t *p_intf )
216 {
217     FILE *f;
218     int i_x, i_y;
219
220     switch( p_intf->p_sys->sensor )
221     {
222     case HDAPS_SENSOR:
223         f = fopen( "/sys/devices/platform/hdaps/position", "r" );
224         if( !f )
225         {
226             return 0;
227         }
228
229         i_x = i_y = 0;
230         fscanf( f, "(%d,%d)", &i_x, &i_y );
231         fclose( f );
232
233         return i_x - p_intf->p_sys->i_calibrate;
234
235     case AMS_SENSOR:
236         f = fopen( "/sys/devices/ams/x", "r" );
237         if( !f )
238         {
239             return 0;
240         }
241
242         fscanf( f, "%d", &i_x);
243         fclose( f );
244
245         return - i_x * 3; /* FIXME: arbitrary */
246
247     default:
248         return 0;
249     }
250 }
251