]> git.sesse.net Git - vlc/blob - modules/access/vcdx/intf.c
intf.c, vcdplayer.c: Add code for multi-default selection lists. But
[vlc] / modules / access / vcdx / intf.c
1 /*****************************************************************************
2  * intf.c: Video CD interface to handle user interaction and still time
3  *****************************************************************************
4  * Copyright (C) 2002 VideoLAN
5  * $Id: intf.c,v 1.4 2003/11/23 03:58:33 rocky Exp $
6  *
7  * Authors: Rocky Bernstein <rocky@panix.com>
8  *   from DVD code by Stéphane Borel <stef@via.ecp.fr>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  * 
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #include <stdlib.h>                                      /* malloc(), free() */
29 #include <string.h>
30 #include <unistd.h>
31
32 #include <vlc/vlc.h>
33 #include <vlc/intf.h>
34
35 #include "stream_control.h"
36 #include "input_ext-intf.h"
37 #include "input_ext-dec.h"
38 #include "vlc_keys.h"
39
40 #include "vcd.h"
41 #include "vcdplayer.h"
42
43 /*****************************************************************************
44  * intf_sys_t: description and status of interface
45  *****************************************************************************/
46 struct intf_sys_t
47 {
48     input_thread_t    * p_input;
49     thread_vcd_data_t * p_vcd;
50
51     vlc_bool_t          b_still;
52     vlc_bool_t          b_inf_still;
53     mtime_t             m_still_time;
54
55 #if FINISHED
56     vcdplay_ctrl_t      control;
57 #else 
58     int                 control;
59 #endif
60     vlc_bool_t          b_click, b_move, b_key_pressed;
61 };
62
63 /*****************************************************************************
64  * Local prototypes.
65  *****************************************************************************/
66 static int  InitThread     ( intf_thread_t *p_intf );
67 static int  MouseEvent     ( vlc_object_t *, char const *,
68                              vlc_value_t, vlc_value_t, void * );
69 static int  KeyEvent       ( vlc_object_t *, char const *,
70                              vlc_value_t, vlc_value_t, void * );
71
72 /* Exported functions */
73 static void RunIntf        ( intf_thread_t *p_intf );
74
75 /*****************************************************************************
76  * OpenIntf: initialize dummy interface
77  *****************************************************************************/
78 int E_(VCDOpenIntf) ( vlc_object_t *p_this )
79 {
80     intf_thread_t *p_intf = (intf_thread_t *)p_this;
81
82     msg_Dbg( p_intf, "VCDOpenIntf" );
83
84     /* Allocate instance and initialize some members */
85     p_intf->p_sys = malloc( sizeof( intf_sys_t ) );
86     if( p_intf->p_sys == NULL )
87     {
88         return( 1 );
89     };
90
91     p_intf->pf_run = RunIntf;
92
93     var_AddCallback( p_intf->p_vlc, "key-pressed", KeyEvent, p_intf );
94     p_intf->p_sys->m_still_time = 0;
95     p_intf->p_sys->b_inf_still = 0;
96     p_intf->p_sys->b_still = 0;
97
98     return( 0 );
99 }
100
101 /*****************************************************************************
102  * CloseIntf: destroy dummy interface
103  *****************************************************************************/
104 void E_(VCDCloseIntf) ( vlc_object_t *p_this )
105 {
106     intf_thread_t *p_intf = (intf_thread_t *)p_this;
107
108     /* Destroy structure */
109     free( p_intf->p_sys );
110 }
111
112
113 /*****************************************************************************
114  * RunIntf: main loop
115  *****************************************************************************/
116 static void RunIntf( intf_thread_t *p_intf )
117 {
118     vlc_object_t      * p_vout = NULL;
119     thread_vcd_data_t * p_vcd;
120     input_thread_t    * p_input;
121     
122     /* What you add to the last input number entry. It accumulates all of
123        the 10_ADD keypresses */
124     int number_addend = 0; 
125     
126     if( InitThread( p_intf ) < 0 )
127     {
128         msg_Err( p_intf, "can't initialize intf" );
129         return;
130     }
131
132     p_input = p_intf->p_sys->p_input;
133     p_vcd   = p_intf->p_sys->p_vcd = 
134       (thread_vcd_data_t *) p_input->p_access_data;
135
136     dbg_print( INPUT_DBG_CALL, "intf initialized" );
137
138     /* Main loop */
139     while( !p_intf->b_die )
140     {
141       vlc_mutex_lock( &p_intf->change_lock );
142
143       /*
144        * keyboard event
145        */
146       if( p_vout && p_intf->p_sys->b_key_pressed )
147         {
148           vlc_value_t val;
149           int i, i_action = -1;
150           struct hotkey *p_hotkeys = p_intf->p_vlc->p_hotkeys;
151
152           p_intf->p_sys->b_key_pressed = VLC_FALSE;
153           
154           /* Find action triggered by hotkey (if any) */
155           var_Get( p_intf->p_vlc, "key-pressed", &val );
156
157           dbg_print( INPUT_DBG_EVENT, "Key pressed %d", val.i_int );
158
159           for( i = 0; p_hotkeys[i].psz_action != NULL; i++ )
160             {
161               if( p_hotkeys[i].i_key == val.i_int )
162                 {
163                   i_action = p_hotkeys[i].i_action;
164                 }
165             }
166           
167           if( i_action != -1) {
168             switch (i_action) {
169               
170             case ACTIONID_NAV_LEFT: 
171               dbg_print( INPUT_DBG_EVENT, "ACTIONID_NAV_LEFT - prev (%d)", 
172                          number_addend );
173               do {
174                 vcdplayer_play_prev( p_input );
175               } while (number_addend-- > 0);
176               break;
177
178             case ACTIONID_NAV_RIGHT:
179               dbg_print( INPUT_DBG_EVENT, "ACTIONID_NAV_RIGHT - next (%d)",
180                          number_addend );
181               do {
182                 vcdplayer_play_next( p_input );
183               } while (number_addend-- > 0);
184               break;
185
186             case ACTIONID_NAV_UP:
187               dbg_print( INPUT_DBG_EVENT, "ACTIONID_NAV_UP - return" );
188               do {
189                 vcdplayer_play_return( p_input );
190               } while (number_addend-- > 0);
191               break;
192
193             case ACTIONID_NAV_DOWN:
194               dbg_print( INPUT_DBG_EVENT, "ACTIONID_NAV_DOWN - default"  );
195               vcdplayer_play_default( p_input );
196               break;
197
198             case ACTIONID_NAV_ACTIVATE: 
199               {
200                 vcdinfo_itemid_t itemid;
201                 itemid.type=p_vcd->play_item.type;
202
203                 dbg_print( INPUT_DBG_EVENT, "ACTIONID_NAV_ACTIVATE" );
204
205                 if ( vcdplayer_pbc_is_on( p_vcd ) && number_addend != 0 ) {
206                   lid_t next_num=vcdinfo_selection_get_lid(p_vcd->vcd, 
207                                                            itemid.num,
208                                                            number_addend);
209                   if (VCDINFO_INVALID_LID != next_num) {
210                     itemid.num  = next_num;
211                     itemid.type = VCDINFO_ITEM_TYPE_LID;
212                     VCDPlay( p_input, itemid );
213                   }
214                 } else {
215                   itemid.num = number_addend;
216                   VCDPlay( p_input, itemid );
217                 }
218                 break;
219               }
220             }
221             number_addend = 0;
222           } else {
223             unsigned int digit_entered=0;
224
225             switch (val.i_int) {
226             case '9':
227               digit_entered++;
228             case '8':
229               digit_entered++;
230             case '7':
231               digit_entered++;
232             case '6':
233               digit_entered++;
234             case '5':
235               digit_entered++;
236             case '4':
237               digit_entered++;
238             case '3':
239               digit_entered++;
240             case '2':
241               digit_entered++;
242             case '1':
243               digit_entered++;
244             case '0':
245               {
246                 number_addend *= 10;
247                 number_addend += digit_entered;
248                 dbg_print( INPUT_DBG_EVENT, 
249                            "Added %d. Number is now: %d\n", 
250                            digit_entered, number_addend);
251                 break;
252               }
253             }
254           }
255         }
256
257       
258       vlc_mutex_unlock( &p_intf->change_lock );
259       
260       if( p_vout == NULL )
261         {
262           p_vout = vlc_object_find( p_intf->p_sys->p_input,
263                                     VLC_OBJECT_VOUT, FIND_CHILD );
264           if( p_vout )
265             {
266               var_AddCallback( p_vout, "mouse-moved", MouseEvent, p_intf );
267               var_AddCallback( p_vout, "mouse-clicked", MouseEvent, p_intf );
268               var_AddCallback( p_vout, "key-pressed", KeyEvent, p_intf );
269             }
270         }
271       
272       
273       /* Wait a bit */
274       msleep( INTF_IDLE_SLEEP );
275     }
276
277     if( p_vout )
278     {
279         var_DelCallback( p_vout, "mouse-moved", MouseEvent, p_intf );
280         var_DelCallback( p_vout, "mouse-clicked", MouseEvent, p_intf );
281         vlc_object_release( p_vout );
282     }
283
284     vlc_object_release( p_intf->p_sys->p_input );
285 }
286
287 /*****************************************************************************
288  * InitThread:
289  *****************************************************************************/
290 static int InitThread( intf_thread_t * p_intf )
291 {
292     /* We might need some locking here */
293     if( !p_intf->b_die )
294     {
295         input_thread_t * p_input;
296
297         p_input = vlc_object_find( p_intf, VLC_OBJECT_INPUT, FIND_PARENT );
298
299         /* Maybe the input just died */
300         if( p_input == NULL )
301         {
302             return VLC_EGENERIC;
303         }
304
305         vlc_mutex_lock( &p_intf->change_lock );
306
307         p_intf->p_sys->p_input = p_input;
308
309         p_intf->p_sys->b_move = VLC_FALSE;
310         p_intf->p_sys->b_click = VLC_FALSE;
311         p_intf->p_sys->b_key_pressed = VLC_FALSE;
312
313         vlc_mutex_unlock( &p_intf->change_lock );
314
315         return VLC_SUCCESS;
316     }
317     else
318     {
319         return VLC_EGENERIC;
320     }
321 }
322
323 /*****************************************************************************
324  * MouseEvent: callback for mouse events
325  *****************************************************************************/
326 static int MouseEvent( vlc_object_t *p_this, char const *psz_var,
327                        vlc_value_t oldval, vlc_value_t newval, void *p_data )
328 {
329     intf_thread_t *p_intf = (intf_thread_t *)p_data;
330
331     vlc_mutex_lock( &p_intf->change_lock );
332
333     if( psz_var[6] == 'c' ) /* "mouse-clicked" */
334     {
335         p_intf->p_sys->b_click = VLC_TRUE;
336     }
337     else if( psz_var[6] == 'm' ) /* "mouse-moved" */
338     {
339         p_intf->p_sys->b_move = VLC_TRUE;
340     }
341
342     vlc_mutex_unlock( &p_intf->change_lock );
343
344     return VLC_SUCCESS;
345 }
346
347 /*****************************************************************************
348  * KeyEvent: callback for keyboard events
349  *****************************************************************************/
350 static int KeyEvent( vlc_object_t *p_this, char const *psz_var,
351                        vlc_value_t oldval, vlc_value_t newval, void *p_data )
352 {
353     intf_thread_t *p_intf = (intf_thread_t *)p_data;
354     vlc_mutex_lock( &p_intf->change_lock );
355
356     p_intf->p_sys->b_key_pressed = VLC_TRUE;
357     
358     vlc_mutex_unlock( &p_intf->change_lock );
359
360     return VLC_SUCCESS;
361 }
362
363 /*****************************************************************************
364  * dvdIntfStillTime: function provided to demux plugin to request
365  * still images
366  *****************************************************************************/
367 int vcdIntfStillTime( intf_thread_t *p_intf, int i_sec )
368 {
369     vlc_mutex_lock( &p_intf->change_lock );
370
371     if( i_sec == 0xff )
372     {
373         p_intf->p_sys->b_still = 1;
374         p_intf->p_sys->b_inf_still = 1;
375     }
376     else if( i_sec > 0 )
377     {
378         p_intf->p_sys->b_still = 1;
379         p_intf->p_sys->m_still_time = 1000000 * i_sec;
380     }
381     vlc_mutex_unlock( &p_intf->change_lock );
382
383     return VLC_SUCCESS;
384 }
385
386 /*****************************************************************************
387  * vcdIntfStillTime: function provided to reset still image
388  *****************************************************************************/
389 int vcdIntfResetStillTime( intf_thread_t *p_intf )
390 {
391     vlc_mutex_lock( &p_intf->change_lock );
392     p_intf->p_sys->m_still_time = 0;
393     input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
394     vlc_mutex_unlock( &p_intf->change_lock );
395
396     return VLC_SUCCESS;
397 }