d723b936d358ffe275a3d84762bb93d75249296b
[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/intf.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_last_x, i_calibrate;
46     int i_threshold;
47 };
48
49 /*****************************************************************************
50  * Local prototypes.
51  *****************************************************************************/
52 static int  Open   ( vlc_object_t * );
53 static void Close  ( vlc_object_t * );
54
55 static void RunIntf( intf_thread_t *p_intf );
56 static int GetOrientation( intf_thread_t *p_intf );
57
58 /*****************************************************************************
59  * Module descriptor
60  *****************************************************************************/
61 vlc_module_begin();
62     set_shortname( _("motion"));
63     set_category( CAT_INTERFACE );
64     set_description( _("motion control interface") );
65
66     set_capability( "interface", 0 );
67     set_callbacks( Open, Close );
68 vlc_module_end();
69
70 /*****************************************************************************
71  * OpenIntf: initialise interface
72  *****************************************************************************/
73 int Open ( vlc_object_t *p_this )
74 {
75     intf_thread_t *p_intf = (intf_thread_t *)p_this;
76     FILE *f;
77     int i_x, i_y;
78
79     p_intf->p_sys = malloc( sizeof( intf_sys_t ) );
80     if( p_intf->p_sys == NULL )
81     {
82         return VLC_ENOMEM;
83     }
84
85     if( access( "/sys/devices/platform/hdaps/position", R_OK ) == 0 )
86     {
87         /* IBM HDAPS support */
88         f = fopen( "/sys/devices/platform/hdaps/calibrate", "r" );
89         if( f )
90         {
91             i_x = i_y = 0;
92             fscanf( f, "(%d,%d)", &i_x, &i_y );
93             fclose( f );
94             p_intf->p_sys->i_calibrate = i_x;
95             p_intf->p_sys->sensor = HDAPS_SENSOR;
96         }
97         else
98         {
99             p_intf->p_sys->sensor = NO_SENSOR;
100         }
101     }
102     else if( access( "/sys/devices/ams/x", R_OK ) == 0 )
103     {
104         /* Apple Motion Sensor support */
105         p_intf->p_sys->sensor = AMS_SENSOR;
106     }
107     else
108     {
109         /* No motion sensor support */
110         p_intf->p_sys->sensor = NO_SENSOR;
111     }
112
113     p_intf->pf_run = RunIntf;
114
115     return VLC_SUCCESS;
116 }
117
118 /*****************************************************************************
119  * CloseIntf: destroy interface
120  *****************************************************************************/
121 void Close ( vlc_object_t *p_this )
122 {
123     intf_thread_t *p_intf = (intf_thread_t *)p_this;
124
125     free( p_intf->p_sys );
126 }
127
128 /*****************************************************************************
129  * RunIntf: main loop
130  *****************************************************************************/
131 static void RunIntf( intf_thread_t *p_intf )
132 {
133     int i_x, i_oldx = 0;
134
135     while( !p_intf->b_die )
136     {
137 #define LOW_THRESHOLD 80
138 #define HIGH_THRESHOLD 100
139         vout_thread_t *p_vout;
140         char *psz_filter, *psz_type;
141         vlc_bool_t b_change = VLC_FALSE;
142
143         /* Wait a bit, get orientation, change filter if necessary */
144         msleep( INTF_IDLE_SLEEP );
145
146         i_x = GetOrientation( p_intf );
147
148         if( i_x < -HIGH_THRESHOLD && i_oldx > -LOW_THRESHOLD )
149         {
150             b_change = VLC_TRUE;
151             psz_filter = "transform";
152             psz_type = "270";
153         }
154         else if( ( i_x > -LOW_THRESHOLD && i_oldx < -HIGH_THRESHOLD )
155                  || ( i_x < LOW_THRESHOLD && i_oldx > HIGH_THRESHOLD ) )
156         {
157             b_change = VLC_TRUE;
158             psz_filter = "";
159             psz_type = "";
160         }
161         else if( i_x > HIGH_THRESHOLD && i_oldx < LOW_THRESHOLD )
162         {
163             b_change = VLC_TRUE;
164             psz_filter = "transform";
165             psz_type = "90";
166         }
167
168         if( !b_change )
169         {
170             continue;
171         }
172
173         p_vout = (vout_thread_t *)
174             vlc_object_find( p_intf, VLC_OBJECT_VOUT, FIND_ANYWHERE );
175         if( !p_vout )
176         {
177             continue;
178         }
179
180         config_PutPsz( p_vout, "transform-type", psz_type );
181         var_SetString( p_vout, "vout-filter", psz_filter );
182         vlc_object_release( p_vout );
183
184         i_oldx = i_x;
185     }
186 }
187
188 /*****************************************************************************
189  * GetOrientation: get laptop orientation, range -180 / +180
190  *****************************************************************************/
191 static int GetOrientation( intf_thread_t *p_intf )
192 {
193     FILE *f;
194     int i_x, i_y;
195
196     switch( p_intf->p_sys->sensor )
197     {
198     case HDAPS_SENSOR:
199         f = fopen( "/sys/devices/platform/hdaps/position", "r" );
200         if( !f )
201         {
202             return 0;
203         }
204
205         i_x = i_y = 0;
206         fscanf( f, "(%d,%d)", &i_x, &i_y );
207         fclose( f );
208
209         return i_x - p_intf->p_sys->i_calibrate;
210
211     case AMS_SENSOR:
212         f = fopen( "/sys/devices/ams/x", "r" );
213         if( !f )
214         {
215             return 0;
216         }
217
218         fscanf( f, "%d", &i_x);
219         fclose( f );
220
221         return - i_x * 3; /* FIXME: arbitrary */
222
223     default:
224         return 0;
225     }
226 }
227