]> git.sesse.net Git - vlc/blob - modules/access/dvdplay/intf.c
* ./modules/access/dvdplay/intf.c: added a sanity check upon initialization
[vlc] / modules / access / dvdplay / intf.c
1 /*****************************************************************************
2  * intf.c: interface for DVD video manager
3  *****************************************************************************
4  * Copyright (C) 2002 VideoLAN
5  * $Id: intf.c,v 1.6 2003/01/29 15:55:44 sam Exp $
6  *
7  * Authors: Stéphane Borel <stef@via.ecp.fr>
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., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <stdlib.h>                                      /* malloc(), free() */
28 #include <string.h>
29 #include <unistd.h>
30
31 #include <vlc/vlc.h>
32 #include <vlc/intf.h>
33
34 #include "stream_control.h"
35 #include "input_ext-intf.h"
36 #include "input_ext-dec.h"
37
38 #include "dvd.h"
39
40 /*****************************************************************************
41  * intf_sys_t: description and status of interface
42  *****************************************************************************/
43 struct intf_sys_t
44 {
45     input_thread_t *    p_input;
46     dvd_data_t *        p_dvd;
47
48     vlc_bool_t          b_still;
49     vlc_bool_t          b_inf_still;
50     mtime_t             m_still_time;
51
52     dvdplay_ctrl_t      control;
53     vlc_bool_t          b_click, b_move, b_key_pressed;
54 };
55
56 /*****************************************************************************
57  * Local prototypes.
58  *****************************************************************************/
59 static int  InitThread     ( intf_thread_t *p_intf );
60 static int  MouseEvent     ( vlc_object_t *, char const *,
61                              vlc_value_t, vlc_value_t, void * );
62 static int  KeyEvent       ( vlc_object_t *, char const *,
63                              vlc_value_t, vlc_value_t, void * );
64
65 /* Exported functions */
66 static void RunIntf        ( intf_thread_t *p_intf );
67
68 /*****************************************************************************
69  * OpenIntf: initialize dummy interface
70  *****************************************************************************/
71 int E_(OpenIntf) ( vlc_object_t *p_this )
72 {
73     intf_thread_t *p_intf = (intf_thread_t *)p_this;
74
75     /* Allocate instance and initialize some members */
76     p_intf->p_sys = malloc( sizeof( intf_sys_t ) );
77     if( p_intf->p_sys == NULL )
78     {
79         return( 1 );
80     };
81
82     p_intf->pf_run = RunIntf;
83
84     p_intf->p_sys->m_still_time = 0;
85     p_intf->p_sys->b_inf_still = 0;
86     p_intf->p_sys->b_still = 0;
87
88     return( 0 );
89 }
90
91 /*****************************************************************************
92  * CloseIntf: destroy dummy interface
93  *****************************************************************************/
94 void E_(CloseIntf) ( vlc_object_t *p_this )
95 {
96     intf_thread_t *p_intf = (intf_thread_t *)p_this;
97
98     /* Destroy structure */
99     free( p_intf->p_sys );
100 }
101
102
103 /*****************************************************************************
104  * RunIntf: main loop
105  *****************************************************************************/
106 static void RunIntf( intf_thread_t *p_intf )
107 {
108     vlc_object_t *      p_vout = NULL;
109     mtime_t             mtime = 0;
110     mtime_t             mlast = 0;
111
112     if( InitThread( p_intf ) < 0 )
113     {
114         msg_Err( p_intf, "can't initialize intf" );
115         return;
116     }
117     msg_Dbg( p_intf, "intf initialized" );
118
119     /* Main loop */
120     while( !p_intf->b_die )
121     {
122         vlc_mutex_lock( &p_intf->change_lock );
123
124         /*
125          * still images
126          */
127 #if 1
128         if( p_intf->p_sys->b_still && !p_intf->p_sys->b_inf_still )
129         {
130             if( p_intf->p_sys->m_still_time > 0 )
131             {
132                 /* update remaining still time */
133                 mtime = mdate();
134                 if( mlast )
135                 {
136                     p_intf->p_sys->m_still_time -= mtime - mlast;
137                 }
138
139                 mlast = mtime;
140             }
141             else
142             {
143                 /* still time elasped */
144                 input_SetStatus( p_intf->p_sys->p_input,
145                                  INPUT_STATUS_PLAY );
146                 p_intf->p_sys->m_still_time = 0;
147                 p_intf->p_sys->b_still = 0;
148                 mlast = 0;
149             }
150         }
151 #else
152         if( p_intf->p_sys->m_still_time != (mtime_t)(-1) )
153         {
154             if( p_intf->p_sys->m_still_time )
155             {
156                 mtime = mdate();
157                 if( mlast )
158                 {
159                     p_intf->p_sys->m_still_time -= mtime - mlast;
160                 }
161                 if( !p_intf->p_sys->m_still_time )
162                 {
163                     input_SetStatus( p_intf->p_sys->p_input,
164                                      INPUT_STATUS_PLAY );
165                 }
166                 mlast = mtime;
167             }
168
169         }
170 #endif
171
172         /* 
173          * mouse cursor
174          */
175         if( p_vout && ( p_intf->p_sys->b_click || p_intf->p_sys->b_move ) )
176         {
177             vlc_value_t val;
178             int i_activate;
179
180             var_Get( p_vout, "mouse-x", &val );
181             p_intf->p_sys->control.mouse.i_x = val.i_int;
182             var_Get( p_vout, "mouse-y", &val );
183             p_intf->p_sys->control.mouse.i_y = val.i_int;
184
185             if( p_intf->p_sys->b_click )
186             {
187                 p_intf->p_sys->control.type = DVDCtrlMouseActivate;
188                 p_intf->p_sys->b_click = VLC_FALSE;
189             }
190             else
191             {
192                 p_intf->p_sys->control.type = DVDCtrlMouseSelect;
193                 p_intf->p_sys->b_move = VLC_FALSE;
194             }
195
196             /* we can safely interact with libdvdplay
197              * with the stream lock */
198             vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
199
200             i_activate = dvdplay_button( p_intf->p_sys->p_dvd->vmg,
201                                          &p_intf->p_sys->control );
202
203             vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
204
205             if( i_activate && p_intf->p_sys->b_still )
206             {
207                 input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
208                 p_intf->p_sys->b_still = 0;
209                 p_intf->p_sys->b_inf_still = 0;
210                 p_intf->p_sys->m_still_time = 0;
211             }
212         }
213
214         /*
215          * keyboard event
216          */
217         if( p_vout && p_intf->p_sys->b_key_pressed )
218         {
219             vlc_value_t val;
220             int i_activate;
221
222             p_intf->p_sys->b_key_pressed = VLC_FALSE;
223             
224             var_Get( p_vout, "key-pressed", &val );
225             if ( val.psz_string )
226             {
227                 if( !strcmp( val.psz_string, "LEFT" ) )
228                 {
229                     p_intf->p_sys->control.type = DVDCtrlLeftButtonSelect;
230                 }
231                 else if( !strcmp( val.psz_string, "RIGHT" ) )
232                 {
233                     p_intf->p_sys->control.type = DVDCtrlRightButtonSelect;
234                 }
235                 else if( !strcmp( val.psz_string, "UP" ) )
236                 {
237                     p_intf->p_sys->control.type = DVDCtrlUpperButtonSelect;
238                 }
239                 else if( !strcmp( val.psz_string, "DOWN" ) )
240                 {
241                     p_intf->p_sys->control.type = DVDCtrlLowerButtonSelect;
242                 }
243                 else if( !strcmp( val.psz_string, "ENTER" ) )
244                 {
245                     p_intf->p_sys->control.type = DVDCtrlButtonActivate;
246                 }
247                 /* we can safely interact with libdvdplay
248                  * with the stream lock */
249                 vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
250                 
251                 i_activate = dvdplay_button( p_intf->p_sys->p_dvd->vmg,
252                                              &p_intf->p_sys->control );
253                 
254                 vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
255                 
256                 if( i_activate && p_intf->p_sys->b_still )
257                 {
258                     input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
259                     p_intf->p_sys->b_still = 0;
260                     p_intf->p_sys->b_inf_still = 0;
261                     p_intf->p_sys->m_still_time = 0;
262                 }
263             }
264         }
265                 
266
267         vlc_mutex_unlock( &p_intf->change_lock );
268
269         /* 
270          * video output
271          */
272         if( p_vout && p_vout->b_die )
273         {
274             var_DelCallback( p_vout, "mouse-moved", MouseEvent, p_intf );
275             var_DelCallback( p_vout, "mouse-clicked", MouseEvent, p_intf );
276             var_DelCallback( p_vout, "key-pressed", KeyEvent, p_intf );
277             vlc_object_release( p_vout );
278             p_vout = NULL;
279         }
280
281         if( p_vout == NULL )
282         {
283             p_vout = vlc_object_find( p_intf->p_sys->p_input,
284                                       VLC_OBJECT_VOUT, FIND_CHILD );
285             if( p_vout )
286             {
287                 var_AddCallback( p_vout, "mouse-moved", MouseEvent, p_intf );
288                 var_AddCallback( p_vout, "mouse-clicked", MouseEvent, p_intf );
289                 var_AddCallback( p_vout, "key-pressed", KeyEvent, p_intf );
290             }
291         }
292
293         /* Wait a bit */
294         msleep( INTF_IDLE_SLEEP );
295     }
296
297     if( p_vout )
298     {
299         var_DelCallback( p_vout, "mouse-moved", MouseEvent, p_intf );
300         var_DelCallback( p_vout, "mouse-clicked", MouseEvent, p_intf );
301         var_DelCallback( p_vout, "key-pressed", KeyEvent, p_intf );
302         vlc_object_release( p_vout );
303     }
304
305     vlc_object_release( p_intf->p_sys->p_input );
306 }
307
308 /*****************************************************************************
309  * InitThread:
310  *****************************************************************************/
311 static int InitThread( intf_thread_t * p_intf )
312 {
313     /* We might need some locking here */
314     if( !p_intf->b_die )
315     {
316         input_thread_t * p_input;
317         dvd_data_t * p_dvd;
318
319         p_input = vlc_object_find( p_intf, VLC_OBJECT_INPUT, FIND_PARENT );
320
321         /* Maybe the input just died */
322         if( p_input == NULL )
323         {
324             return VLC_EGENERIC;
325         }
326
327         p_dvd = (dvd_data_t*)p_input->p_access_data;
328         p_dvd->p_intf = p_intf;
329
330         vlc_mutex_lock( &p_intf->change_lock );
331
332         p_intf->p_sys->p_input = p_input;
333         p_intf->p_sys->p_dvd = p_dvd;
334
335         p_intf->p_sys->b_move = VLC_FALSE;
336         p_intf->p_sys->b_click = VLC_FALSE;
337         p_intf->p_sys->b_key_pressed = VLC_FALSE;
338
339         vlc_mutex_unlock( &p_intf->change_lock );
340
341         return VLC_SUCCESS;
342     }
343     else
344     {
345         return VLC_EGENERIC;
346     }
347 }
348
349 /*****************************************************************************
350  * MouseEvent: callback for mouse events
351  *****************************************************************************/
352 static int MouseEvent( vlc_object_t *p_this, char const *psz_var,
353                        vlc_value_t oldval, vlc_value_t newval, void *p_data )
354 {
355     intf_thread_t *p_intf = (intf_thread_t *)p_data;
356
357     vlc_mutex_lock( &p_intf->change_lock );
358
359     if( psz_var[6] == 'c' ) /* "mouse-clicked" */
360     {
361         p_intf->p_sys->b_click = VLC_TRUE;
362     }
363     else if( psz_var[6] == 'm' ) /* "mouse-moved" */
364     {
365         p_intf->p_sys->b_move = VLC_TRUE;
366     }
367
368     vlc_mutex_unlock( &p_intf->change_lock );
369
370     return VLC_SUCCESS;
371 }
372
373 /*****************************************************************************
374  * KeyEvent: callback for keyboard events
375  *****************************************************************************/
376 static int KeyEvent( vlc_object_t *p_this, char const *psz_var,
377                        vlc_value_t oldval, vlc_value_t newval, void *p_data )
378 {
379     intf_thread_t *p_intf = (intf_thread_t *)p_data;
380     vlc_mutex_lock( &p_intf->change_lock );
381
382     p_intf->p_sys->b_key_pressed = VLC_TRUE;
383     
384     vlc_mutex_unlock( &p_intf->change_lock );
385
386     return VLC_SUCCESS;
387 }
388
389 /*****************************************************************************
390  * dvdIntfStillTime: function provided to demux plugin to request
391  * still images
392  *****************************************************************************/
393 int dvdIntfStillTime( intf_thread_t *p_intf, int i_sec )
394 {
395     vlc_mutex_lock( &p_intf->change_lock );
396 #if 1
397
398     if( i_sec == 0xff )
399     {
400         p_intf->p_sys->b_still = 1;
401         p_intf->p_sys->b_inf_still = 1;
402     }
403     else if( i_sec > 0 )
404     {
405         p_intf->p_sys->b_still = 1;
406         p_intf->p_sys->m_still_time = 1000000 * i_sec;
407     }
408 #else
409     if( i_sec > 0 )
410     {
411         if( i_sec == 0xff )
412         {
413             p_intf->p_sys->m_still_time = (mtime_t)(-1);
414             msg_Warn( p_intf, I64Fd, p_intf->p_sys->m_still_time );
415         }
416         else
417         {
418             p_intf->p_sys->m_still_time = 1000000 * i_sec;
419         }
420     }
421 #endif
422     vlc_mutex_unlock( &p_intf->change_lock );
423
424     return VLC_SUCCESS;
425 }
426