]> git.sesse.net Git - vlc/blob - modules/access/vcdx/intf.c
6b2ce0709217889e9635f5e3d3c6d63f1a385c28
[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,2003 VideoLAN
5  * $Id: intf.c,v 1.11 2003/12/05 05:01:17 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 <vlc/vlc.h>
29 #include <vlc/intf.h>
30
31 #include "stream_control.h"
32 #include "input_ext-intf.h"
33 #include "input_ext-dec.h"
34 #include "vlc_keys.h"
35
36 #include "vcd.h"
37 #include "vcdplayer.h"
38 #include "intf.h"
39
40 /*****************************************************************************
41  * Local prototypes.
42  *****************************************************************************/
43 static int  InitThread     ( intf_thread_t *p_intf );
44 static int  KeyEvent       ( vlc_object_t *, char const *,
45                              vlc_value_t, vlc_value_t, void * );
46
47 /* Exported functions */
48 static void RunIntf        ( intf_thread_t *p_intf );
49
50 /*****************************************************************************
51  * OpenIntf: initialize dummy interface
52  *****************************************************************************/
53 int E_(OpenIntf) ( vlc_object_t *p_this )
54 {
55     intf_thread_t *p_intf = (intf_thread_t *)p_this;
56
57     msg_Dbg( p_intf, "VCDOpenIntf" );
58
59     /* Allocate instance and initialize some members */
60     p_intf->p_sys = malloc( sizeof( intf_sys_t ) );
61     if( p_intf->p_sys == NULL )
62     {
63         return( 1 );
64     };
65
66     p_intf->pf_run = RunIntf;
67
68     var_AddCallback( p_intf->p_vlc, "key-pressed", KeyEvent, p_intf );
69     p_intf->p_sys->m_still_time = 0;
70     p_intf->p_sys->b_inf_still = 0;
71     p_intf->p_sys->b_still = 0;
72
73     return( 0 );
74 }
75
76 /*****************************************************************************
77  * CloseIntf: destroy dummy interface
78  *****************************************************************************/
79 void E_(CloseIntf) ( vlc_object_t *p_this )
80 {
81     intf_thread_t *p_intf = (intf_thread_t *)p_this;
82     var_DelCallback( p_intf->p_vlc, "key-pressed", KeyEvent, p_intf );
83
84     /* Destroy structure */
85     free( p_intf->p_sys );
86 }
87
88
89 /*****************************************************************************
90  * RunIntf: main loop
91  *****************************************************************************/
92 static void RunIntf( intf_thread_t *p_intf )
93 {
94     vlc_object_t      * p_vout = NULL;
95     mtime_t             mtime = 0;
96     mtime_t             mlast = 0;
97     thread_vcd_data_t * p_vcd;
98     input_thread_t    * p_input;
99     
100     /* What you add to the last input number entry. It accumulates all of
101        the 10_ADD keypresses */
102     int number_addend = 0; 
103     
104     if( InitThread( p_intf ) < 0 )
105     {
106         msg_Err( p_intf, "can't initialize intf" );
107         return;
108     }
109
110     p_input = p_intf->p_sys->p_input;
111     p_vcd   = p_intf->p_sys->p_vcd = 
112       (thread_vcd_data_t *) p_input->p_access_data;
113
114     dbg_print( INPUT_DBG_CALL, "intf initialized" );
115
116     /* Main loop */
117     while( !p_intf->b_die )
118     {
119       vlc_mutex_lock( &p_intf->change_lock );
120
121         /*
122          * Have we timed-out in showing a still frame? 
123          */
124         if( p_intf->p_sys->b_still && !p_intf->p_sys->b_inf_still )
125         {
126             if( p_intf->p_sys->m_still_time > 0 )
127             {
128                 /* Update remaining still time */
129                 dbg_print(INPUT_DBG_STILL, "updating still time");
130                 mtime = mdate();
131                 if( mlast )
132                 {
133                     p_intf->p_sys->m_still_time -= mtime - mlast;
134                 }
135
136                 mlast = mtime;
137             }
138             else
139             {
140                 /* Still time has elasped; set to continue playing. */
141                 dbg_print(INPUT_DBG_STILL, "wait time done - setting play");
142                 input_SetStatus( p_intf->p_sys->p_input,
143                                  INPUT_STATUS_PLAY );
144                 p_intf->p_sys->m_still_time = 0;
145                 p_intf->p_sys->b_still = 0;
146                 mlast = 0;
147             }
148         }
149
150       /*
151        * Do we have a keyboard event? 
152        */
153       if( p_vout && p_intf->p_sys->b_key_pressed )
154         {
155           vlc_value_t val;
156           int i, i_action = -1;
157           struct hotkey *p_hotkeys = p_intf->p_vlc->p_hotkeys;
158
159           p_intf->p_sys->b_key_pressed = VLC_FALSE;
160           
161           /* Find action triggered by hotkey (if any) */
162           var_Get( p_intf->p_vlc, "key-pressed", &val );
163
164           dbg_print( INPUT_DBG_EVENT, "Key pressed %d", val.i_int );
165
166           for( i = 0; p_hotkeys[i].psz_action != NULL; i++ )
167             {
168               if( p_hotkeys[i].i_key == val.i_int )
169                 {
170                   i_action = p_hotkeys[i].i_action;
171                 }
172             }
173           
174           if( i_action != -1) {
175             switch (i_action) {
176               
177             case ACTIONID_NAV_LEFT: 
178               dbg_print( INPUT_DBG_EVENT, "ACTIONID_NAV_LEFT - prev (%d)", 
179                          number_addend );
180               do {
181                 vcdplayer_play_prev( p_input );
182               } while (number_addend-- > 0);
183               break;
184
185             case ACTIONID_NAV_RIGHT:
186               dbg_print( INPUT_DBG_EVENT, "ACTIONID_NAV_RIGHT - next (%d)",
187                          number_addend );
188               do {
189                 vcdplayer_play_next( p_input );
190               } while (number_addend-- > 0);
191               break;
192
193             case ACTIONID_NAV_UP:
194               dbg_print( INPUT_DBG_EVENT, "ACTIONID_NAV_UP - return" );
195               do {
196                 vcdplayer_play_return( p_input );
197               } while (number_addend-- > 0);
198               break;
199
200             case ACTIONID_NAV_DOWN:
201               dbg_print( INPUT_DBG_EVENT, "ACTIONID_NAV_DOWN - default"  );
202               vcdplayer_play_default( p_input );
203               break;
204
205             case ACTIONID_NAV_ACTIVATE: 
206               {
207                 vcdinfo_itemid_t itemid;
208                 itemid.type=p_vcd->play_item.type;
209
210                 dbg_print( INPUT_DBG_EVENT, "ACTIONID_NAV_ACTIVATE" );
211
212                 if ( vcdplayer_pbc_is_on( p_vcd ) && number_addend != 0 ) {
213                   lid_t next_num=vcdinfo_selection_get_lid(p_vcd->vcd, 
214                                                            p_vcd->cur_lid,
215                                                            number_addend);
216                   if (VCDINFO_INVALID_LID != next_num) {
217                     itemid.num  = next_num;
218                     itemid.type = VCDINFO_ITEM_TYPE_LID;
219                     VCDPlay( p_input, itemid );
220                   }
221                 } else {
222                   itemid.num = number_addend;
223                   VCDPlay( p_input, itemid );
224                 }
225                 break;
226               }
227             }
228             number_addend = 0;
229
230             /* Any keypress gets rid of still frame waiting.
231                FIXME - should handle just the ones that cause an action.
232             */
233             if( p_intf->p_sys->b_still )
234               {
235                 dbg_print(INPUT_DBG_STILL, "Playing still after activate");
236                 input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
237                 p_intf->p_sys->b_still = 0;
238                 p_intf->p_sys->b_inf_still = 0;
239                 p_intf->p_sys->m_still_time = 0;
240               }
241
242           } else {
243             unsigned int digit_entered=0;
244
245             switch (val.i_int) {
246             case '9':
247               digit_entered++;
248             case '8':
249               digit_entered++;
250             case '7':
251               digit_entered++;
252             case '6':
253               digit_entered++;
254             case '5':
255               digit_entered++;
256             case '4':
257               digit_entered++;
258             case '3':
259               digit_entered++;
260             case '2':
261               digit_entered++;
262             case '1':
263               digit_entered++;
264             case '0':
265               {
266                 number_addend *= 10;
267                 number_addend += digit_entered;
268                 dbg_print( INPUT_DBG_EVENT, 
269                            "Added %d. Number is now: %d\n", 
270                            digit_entered, number_addend);
271                 break;
272               }
273             }
274           }
275         }
276
277       
278       vlc_mutex_unlock( &p_intf->change_lock );
279       
280       if( p_vout == NULL )
281         {
282           p_vout = vlc_object_find( p_intf->p_sys->p_input,
283                                     VLC_OBJECT_VOUT, FIND_CHILD );
284           if( p_vout )
285             {
286               var_AddCallback( p_vout, "key-pressed", KeyEvent, p_intf );
287             }
288         }
289       
290       
291       /* Wait a bit */
292       msleep( INTF_IDLE_SLEEP );
293     }
294
295     if( p_vout )
296     {
297         var_DelCallback( p_vout, "key-pressed", KeyEvent, p_intf );
298         vlc_object_release( p_vout );
299     }
300
301     vlc_object_release( p_intf->p_sys->p_input );
302 }
303
304 /*****************************************************************************
305  * InitThread:
306  *****************************************************************************/
307 static int InitThread( intf_thread_t * p_intf )
308 {
309     /* We might need some locking here */
310     if( !p_intf->b_die )
311     {
312         input_thread_t * p_input;
313
314         p_input = vlc_object_find( p_intf, VLC_OBJECT_INPUT, FIND_PARENT );
315
316         /* Maybe the input just died */
317         if( p_input == NULL )
318         {
319             return VLC_EGENERIC;
320         }
321
322         vlc_mutex_lock( &p_intf->change_lock );
323
324         p_intf->p_sys->p_input = p_input;
325
326         p_intf->p_sys->b_move = VLC_FALSE;
327         p_intf->p_sys->b_click = VLC_FALSE;
328         p_intf->p_sys->b_key_pressed = VLC_FALSE;
329
330         vlc_mutex_unlock( &p_intf->change_lock );
331
332         return VLC_SUCCESS;
333     }
334     else
335     {
336         return VLC_EGENERIC;
337     }
338 }
339
340 /*****************************************************************************
341  * KeyEvent: callback for keyboard events
342  *****************************************************************************/
343 static int KeyEvent( vlc_object_t *p_this, char const *psz_var,
344                        vlc_value_t oldval, vlc_value_t newval, void *p_data )
345 {
346     intf_thread_t *p_intf = (intf_thread_t *)p_data;
347     vlc_mutex_lock( &p_intf->change_lock );
348
349     p_intf->p_sys->b_key_pressed = VLC_TRUE;
350     
351     vlc_mutex_unlock( &p_intf->change_lock );
352
353     return VLC_SUCCESS;
354 }
355
356 /*****************************************************************************
357  * vcdIntfStillTime: function provided to demux plugin to request
358  * still images
359  *****************************************************************************/
360 int vcdIntfStillTime( intf_thread_t *p_intf, int i_sec )
361 {
362     vlc_mutex_lock( &p_intf->change_lock );
363
364     if( i_sec == -1 )
365     {
366         p_intf->p_sys->b_still     = 1;
367         p_intf->p_sys->b_inf_still = 1;
368     }
369     else if( i_sec > 0 )
370     {
371         p_intf->p_sys->b_still = 1;
372         p_intf->p_sys->m_still_time = 1000000 * i_sec;
373     }
374     vlc_mutex_unlock( &p_intf->change_lock );
375
376     return VLC_SUCCESS;
377 }
378
379 /*****************************************************************************
380  * vcdIntfStillTime: function provided to reset still image
381  *****************************************************************************/
382 int vcdIntfResetStillTime( intf_thread_t *p_intf )
383 {
384     vlc_mutex_lock( &p_intf->change_lock );
385     p_intf->p_sys->m_still_time = 0;
386     input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
387     vlc_mutex_unlock( &p_intf->change_lock );
388
389     return VLC_SUCCESS;
390 }