]> git.sesse.net Git - vlc/blob - modules/access/dvdplay/intf.c
378b2769e50552fb485fe9516f4652d8b0541eb3
[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.8 2003/10/26 13:10:05 sigmunau 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     var_AddCallback( p_intf->p_vlc, "key-pressed", KeyEvent, p_intf );
85     p_intf->p_sys->m_still_time = 0;
86     p_intf->p_sys->b_inf_still = 0;
87     p_intf->p_sys->b_still = 0;
88
89     return( 0 );
90 }
91
92 /*****************************************************************************
93  * CloseIntf: destroy dummy interface
94  *****************************************************************************/
95 void E_(CloseIntf) ( vlc_object_t *p_this )
96 {
97     intf_thread_t *p_intf = (intf_thread_t *)p_this;
98     var_DelCallback( p_intf->p_vlc, "key-pressed", KeyEvent, p_intf );
99     /* Destroy structure */
100     free( p_intf->p_sys );
101 }
102
103
104 /*****************************************************************************
105  * RunIntf: main loop
106  *****************************************************************************/
107 static void RunIntf( intf_thread_t *p_intf )
108 {
109     vlc_object_t *      p_vout = NULL;
110     mtime_t             mtime = 0;
111     mtime_t             mlast = 0;
112     int i_nav_up = config_GetInt( p_intf, "nav-up-key" );
113     int i_nav_down = config_GetInt( p_intf, "nav-down-key" );
114     int i_nav_left = config_GetInt( p_intf, "nav-left-key" );
115     int i_nav_right = config_GetInt( p_intf, "nav-right-key" );
116     int i_nav_activate = config_GetInt( p_intf, "nav-activate-key" );
117
118     if( InitThread( p_intf ) < 0 )
119     {
120         msg_Err( p_intf, "can't initialize intf" );
121         return;
122     }
123     msg_Dbg( p_intf, "intf initialized" );
124
125     /* Main loop */
126     while( !p_intf->b_die )
127     {
128         vlc_mutex_lock( &p_intf->change_lock );
129
130         /*
131          * still images
132          */
133 #if 1
134         if( p_intf->p_sys->b_still && !p_intf->p_sys->b_inf_still )
135         {
136             if( p_intf->p_sys->m_still_time > 0 )
137             {
138                 /* update remaining still time */
139                 mtime = mdate();
140                 if( mlast )
141                 {
142                     p_intf->p_sys->m_still_time -= mtime - mlast;
143                 }
144
145                 mlast = mtime;
146             }
147             else
148             {
149                 /* still time elasped */
150                 input_SetStatus( p_intf->p_sys->p_input,
151                                  INPUT_STATUS_PLAY );
152                 p_intf->p_sys->m_still_time = 0;
153                 p_intf->p_sys->b_still = 0;
154                 mlast = 0;
155             }
156         }
157 #else
158         if( p_intf->p_sys->m_still_time != (mtime_t)(-1) )
159         {
160             if( p_intf->p_sys->m_still_time )
161             {
162                 mtime = mdate();
163                 if( mlast )
164                 {
165                     p_intf->p_sys->m_still_time -= mtime - mlast;
166                 }
167                 if( !p_intf->p_sys->m_still_time )
168                 {
169                     input_SetStatus( p_intf->p_sys->p_input,
170                                      INPUT_STATUS_PLAY );
171                 }
172                 mlast = mtime;
173             }
174
175         }
176 #endif
177
178         /* 
179          * mouse cursor
180          */
181         if( p_vout && ( p_intf->p_sys->b_click || p_intf->p_sys->b_move ) )
182         {
183             vlc_value_t val;
184             int i_activate;
185
186             var_Get( p_vout, "mouse-x", &val );
187             p_intf->p_sys->control.mouse.i_x = val.i_int;
188             var_Get( p_vout, "mouse-y", &val );
189             p_intf->p_sys->control.mouse.i_y = val.i_int;
190
191             if( p_intf->p_sys->b_click )
192             {
193                 p_intf->p_sys->control.type = DVDCtrlMouseActivate;
194                 p_intf->p_sys->b_click = VLC_FALSE;
195             }
196             else
197             {
198                 p_intf->p_sys->control.type = DVDCtrlMouseSelect;
199                 p_intf->p_sys->b_move = VLC_FALSE;
200             }
201
202             /* we can safely interact with libdvdplay
203              * with the stream lock */
204             vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
205
206             i_activate = dvdplay_button( p_intf->p_sys->p_dvd->vmg,
207                                          &p_intf->p_sys->control );
208
209             vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
210
211             if( i_activate && p_intf->p_sys->b_still )
212             {
213                 input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
214                 p_intf->p_sys->b_still = 0;
215                 p_intf->p_sys->b_inf_still = 0;
216                 p_intf->p_sys->m_still_time = 0;
217             }
218         }
219
220         /*
221          * keyboard event
222          */
223         if( p_intf->p_sys->b_key_pressed )
224         {
225             vlc_value_t val;
226             int i_activate;
227
228             p_intf->p_sys->b_key_pressed = VLC_FALSE;
229             
230             var_Get( p_intf->p_vlc, "key-pressed", &val );
231             if ( val.i_int )
232             {
233                 if( val.i_int == i_nav_left )
234                 {
235                     p_intf->p_sys->control.type = DVDCtrlLeftButtonSelect;
236                 }
237                 else if( val.i_int == i_nav_right )
238                 {
239                     p_intf->p_sys->control.type = DVDCtrlRightButtonSelect;
240                 }
241                 else if( val.i_int == i_nav_up )
242                 {
243                     p_intf->p_sys->control.type = DVDCtrlUpperButtonSelect;
244                 }
245                 else if( val.i_int == i_nav_down )
246                 {
247                     p_intf->p_sys->control.type = DVDCtrlLowerButtonSelect;
248                 }
249                 else if( val.i_int == i_nav_activate )
250                 {
251                     p_intf->p_sys->control.type = DVDCtrlButtonActivate;
252                 }
253                 /* we can safely interact with libdvdplay
254                  * with the stream lock */
255                 vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
256                 
257                 i_activate = dvdplay_button( p_intf->p_sys->p_dvd->vmg,
258                                              &p_intf->p_sys->control );
259                 
260                 vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
261                 
262                 if( i_activate && p_intf->p_sys->b_still )
263                 {
264                     input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
265                     p_intf->p_sys->b_still = 0;
266                     p_intf->p_sys->b_inf_still = 0;
267                     p_intf->p_sys->m_still_time = 0;
268                 }
269             }
270         }
271                 
272
273         vlc_mutex_unlock( &p_intf->change_lock );
274
275         /* 
276          * video output
277          */
278         if( p_vout && p_vout->b_die )
279         {
280             var_DelCallback( p_vout, "mouse-moved", MouseEvent, p_intf );
281             var_DelCallback( p_vout, "mouse-clicked", MouseEvent, p_intf );
282             vlc_object_release( p_vout );
283             p_vout = NULL;
284         }
285
286         if( p_vout == NULL )
287         {
288             p_vout = vlc_object_find( p_intf->p_sys->p_input,
289                                       VLC_OBJECT_VOUT, FIND_CHILD );
290             if( p_vout )
291             {
292                 var_AddCallback( p_vout, "mouse-moved", MouseEvent, p_intf );
293                 var_AddCallback( p_vout, "mouse-clicked", MouseEvent, p_intf );
294             }
295         }
296
297         /* Wait a bit */
298         msleep( INTF_IDLE_SLEEP );
299     }
300
301     if( p_vout )
302     {
303         var_DelCallback( p_vout, "mouse-moved", MouseEvent, p_intf );
304         var_DelCallback( p_vout, "mouse-clicked", MouseEvent, p_intf );
305         vlc_object_release( p_vout );
306     }
307
308     vlc_object_release( p_intf->p_sys->p_input );
309 }
310
311 /*****************************************************************************
312  * InitThread:
313  *****************************************************************************/
314 static int InitThread( intf_thread_t * p_intf )
315 {
316     /* We might need some locking here */
317     if( !p_intf->b_die )
318     {
319         input_thread_t * p_input;
320         dvd_data_t * p_dvd;
321
322         p_input = vlc_object_find( p_intf, VLC_OBJECT_INPUT, FIND_PARENT );
323
324         /* Maybe the input just died */
325         if( p_input == NULL )
326         {
327             return VLC_EGENERIC;
328         }
329
330         p_dvd = (dvd_data_t*)p_input->p_access_data;
331         p_dvd->p_intf = p_intf;
332
333         vlc_mutex_lock( &p_intf->change_lock );
334
335         p_intf->p_sys->p_input = p_input;
336         p_intf->p_sys->p_dvd = p_dvd;
337
338         p_intf->p_sys->b_move = VLC_FALSE;
339         p_intf->p_sys->b_click = VLC_FALSE;
340         p_intf->p_sys->b_key_pressed = VLC_FALSE;
341
342         vlc_mutex_unlock( &p_intf->change_lock );
343
344         return VLC_SUCCESS;
345     }
346     else
347     {
348         return VLC_EGENERIC;
349     }
350 }
351
352 /*****************************************************************************
353  * MouseEvent: callback for mouse events
354  *****************************************************************************/
355 static int MouseEvent( vlc_object_t *p_this, char const *psz_var,
356                        vlc_value_t oldval, vlc_value_t newval, void *p_data )
357 {
358     intf_thread_t *p_intf = (intf_thread_t *)p_data;
359
360     vlc_mutex_lock( &p_intf->change_lock );
361
362     if( psz_var[6] == 'c' ) /* "mouse-clicked" */
363     {
364         p_intf->p_sys->b_click = VLC_TRUE;
365     }
366     else if( psz_var[6] == 'm' ) /* "mouse-moved" */
367     {
368         p_intf->p_sys->b_move = VLC_TRUE;
369     }
370
371     vlc_mutex_unlock( &p_intf->change_lock );
372
373     return VLC_SUCCESS;
374 }
375
376 /*****************************************************************************
377  * KeyEvent: callback for keyboard events
378  *****************************************************************************/
379 static int KeyEvent( vlc_object_t *p_this, char const *psz_var,
380                        vlc_value_t oldval, vlc_value_t newval, void *p_data )
381 {
382     intf_thread_t *p_intf = (intf_thread_t *)p_data;
383     vlc_mutex_lock( &p_intf->change_lock );
384
385     p_intf->p_sys->b_key_pressed = VLC_TRUE;
386     
387     vlc_mutex_unlock( &p_intf->change_lock );
388
389     return VLC_SUCCESS;
390 }
391
392 /*****************************************************************************
393  * dvdIntfStillTime: function provided to demux plugin to request
394  * still images
395  *****************************************************************************/
396 int dvdIntfStillTime( intf_thread_t *p_intf, int i_sec )
397 {
398     vlc_mutex_lock( &p_intf->change_lock );
399 #if 1
400
401     if( i_sec == 0xff )
402     {
403         p_intf->p_sys->b_still = 1;
404         p_intf->p_sys->b_inf_still = 1;
405     }
406     else if( i_sec > 0 )
407     {
408         p_intf->p_sys->b_still = 1;
409         p_intf->p_sys->m_still_time = 1000000 * i_sec;
410     }
411 #else
412     if( i_sec > 0 )
413     {
414         if( i_sec == 0xff )
415         {
416             p_intf->p_sys->m_still_time = (mtime_t)(-1);
417             msg_Warn( p_intf, I64Fd, p_intf->p_sys->m_still_time );
418         }
419         else
420         {
421             p_intf->p_sys->m_still_time = 1000000 * i_sec;
422         }
423     }
424 #endif
425     vlc_mutex_unlock( &p_intf->change_lock );
426
427     return VLC_SUCCESS;
428 }
429
430 /*****************************************************************************
431  * dvdIntfStillTime: function provided to reset still image
432  *****************************************************************************/
433 int dvdIntfResetStillTime( intf_thread_t *p_intf )
434 {
435     vlc_mutex_lock( &p_intf->change_lock );
436     p_intf->p_sys->m_still_time = 0;
437     input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
438     vlc_mutex_unlock( &p_intf->change_lock );
439
440     return VLC_SUCCESS;
441 }