]> git.sesse.net Git - vlc/blob - modules/access/vcdx/intf.c
69045cb7fffefd6bfa050a559db9250666ace8bb
[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$
6  *
7  * Author: 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                 var_SetInteger( p_intf->p_sys->p_input, "state", PLAYING_S );
143                 p_intf->p_sys->m_still_time = 0;
144                 p_intf->p_sys->b_still = 0;
145                 mlast = 0;
146             }
147         }
148
149       /*
150        * Do we have a keyboard event?
151        */
152       if( p_vout && p_intf->p_sys->b_key_pressed )
153         {
154           vlc_value_t val;
155           int i, i_action = -1;
156           struct hotkey *p_hotkeys = p_intf->p_vlc->p_hotkeys;
157
158           p_intf->p_sys->b_key_pressed = VLC_FALSE;
159
160           /* Find action triggered by hotkey (if any) */
161           var_Get( p_intf->p_vlc, "key-pressed", &val );
162
163           dbg_print( INPUT_DBG_EVENT, "Key pressed %d", val.i_int );
164
165           for( i = 0; p_hotkeys[i].psz_action != NULL; i++ )
166             {
167               if( p_hotkeys[i].i_key == val.i_int )
168                 {
169                   i_action = p_hotkeys[i].i_action;
170                 }
171             }
172
173           if( i_action != -1) {
174             switch (i_action) {
175
176             case ACTIONID_NAV_LEFT:
177               dbg_print( INPUT_DBG_EVENT, "ACTIONID_NAV_LEFT - prev (%d)",
178                          number_addend );
179               do {
180                 vcdplayer_play_prev( p_input );
181               }        while (number_addend-- > 0);
182               break;
183
184             case ACTIONID_NAV_RIGHT:
185               dbg_print( INPUT_DBG_EVENT, "ACTIONID_NAV_RIGHT - next (%d)",
186                          number_addend );
187               do {
188                 vcdplayer_play_next( p_input );
189               } while (number_addend-- > 0);
190               break;
191
192             case ACTIONID_NAV_UP:
193               dbg_print( INPUT_DBG_EVENT, "ACTIONID_NAV_UP - return" );
194               do {
195                 vcdplayer_play_return( p_input );
196               } while (number_addend-- > 0);
197               break;
198
199             case ACTIONID_NAV_DOWN:
200               dbg_print( INPUT_DBG_EVENT, "ACTIONID_NAV_DOWN - default"  );
201               vcdplayer_play_default( p_input );
202               break;
203
204             case ACTIONID_NAV_ACTIVATE:
205               {
206                 vcdinfo_itemid_t itemid;
207                 itemid.type=p_vcd->play_item.type;
208
209                 dbg_print( INPUT_DBG_EVENT, "ACTIONID_NAV_ACTIVATE" );
210
211                 if ( vcdplayer_pbc_is_on( p_vcd ) && number_addend != 0 ) {
212                   lid_t next_num=vcdinfo_selection_get_lid(p_vcd->vcd,
213                                                            p_vcd->cur_lid,
214                                                            number_addend);
215                   if (VCDINFO_INVALID_LID != next_num) {
216                     itemid.num  = next_num;
217                     itemid.type = VCDINFO_ITEM_TYPE_LID;
218                     VCDPlay( p_input, itemid );
219                   }
220                 } else {
221                   itemid.num = number_addend;
222                   VCDPlay( p_input, itemid );
223                 }
224                 break;
225               }
226             }
227             number_addend = 0;
228
229             /* Any keypress gets rid of still frame waiting.
230                FIXME - should handle just the ones that cause an action.
231             */
232             if( p_intf->p_sys->b_still )
233               {
234                 dbg_print(INPUT_DBG_STILL, "Playing still after activate");
235                 var_SetInteger( p_intf->p_sys->p_input, "state", PLAYING_S );
236                 p_intf->p_sys->b_still = 0;
237                 p_intf->p_sys->b_inf_still = 0;
238                 p_intf->p_sys->m_still_time = 0;
239               }
240
241           } else {
242             unsigned int digit_entered=0;
243
244             switch (val.i_int) {
245             case '9':
246               digit_entered++;
247             case '8':
248               digit_entered++;
249             case '7':
250               digit_entered++;
251             case '6':
252               digit_entered++;
253             case '5':
254               digit_entered++;
255             case '4':
256               digit_entered++;
257             case '3':
258               digit_entered++;
259             case '2':
260               digit_entered++;
261             case '1':
262               digit_entered++;
263             case '0':
264               {
265                 number_addend *= 10;
266                 number_addend += digit_entered;
267                 dbg_print( INPUT_DBG_EVENT,
268                            "Added %d. Number is now: %d\n",
269                            digit_entered, number_addend);
270                 break;
271               }
272             }
273           }
274         }
275
276
277       vlc_mutex_unlock( &p_intf->change_lock );
278
279       if( p_vout == NULL )
280         {
281           p_vout = vlc_object_find( p_intf->p_sys->p_input,
282                                     VLC_OBJECT_VOUT, FIND_CHILD );
283           if( p_vout )
284             {
285               var_AddCallback( p_vout, "key-pressed", KeyEvent, p_intf );
286             }
287         }
288
289
290       /* Wait a bit */
291       msleep( INTF_IDLE_SLEEP );
292     }
293
294     if( p_vout )
295     {
296         var_DelCallback( p_vout, "key-pressed", KeyEvent, p_intf );
297         vlc_object_release( p_vout );
298     }
299
300     vlc_object_release( p_intf->p_sys->p_input );
301 }
302
303 /*****************************************************************************
304  * InitThread:
305  *****************************************************************************/
306 static int InitThread( intf_thread_t * p_intf )
307 {
308     /* We might need some locking here */
309     if( !p_intf->b_die )
310     {
311         input_thread_t * p_input;
312
313         p_input = vlc_object_find( p_intf, VLC_OBJECT_INPUT, FIND_PARENT );
314
315         /* Maybe the input just died */
316         if( p_input == NULL )
317         {
318             return VLC_EGENERIC;
319         }
320
321         vlc_mutex_lock( &p_intf->change_lock );
322
323         p_intf->p_sys->p_input = p_input;
324
325         p_intf->p_sys->b_move = VLC_FALSE;
326         p_intf->p_sys->b_click = VLC_FALSE;
327         p_intf->p_sys->b_key_pressed = VLC_FALSE;
328
329         vlc_mutex_unlock( &p_intf->change_lock );
330
331         return VLC_SUCCESS;
332     }
333     else
334     {
335         return VLC_EGENERIC;
336     }
337 }
338
339 /*****************************************************************************
340  * KeyEvent: callback for keyboard events
341  *****************************************************************************/
342 static int KeyEvent( vlc_object_t *p_this, char const *psz_var,
343                        vlc_value_t oldval, vlc_value_t newval, void *p_data )
344 {
345     intf_thread_t *p_intf = (intf_thread_t *)p_data;
346     vlc_mutex_lock( &p_intf->change_lock );
347
348     p_intf->p_sys->b_key_pressed = VLC_TRUE;
349
350     vlc_mutex_unlock( &p_intf->change_lock );
351
352     return VLC_SUCCESS;
353 }
354
355 /*****************************************************************************
356  * vcdIntfStillTime: function provided to demux plugin to request
357  * still images
358  *****************************************************************************/
359 int vcdIntfStillTime( intf_thread_t *p_intf, int i_sec )
360 {
361     vlc_mutex_lock( &p_intf->change_lock );
362
363     if( i_sec == -1 )
364     {
365         p_intf->p_sys->b_still     = 1;
366         p_intf->p_sys->b_inf_still = 1;
367     }
368     else if( i_sec > 0 )
369     {
370         p_intf->p_sys->b_still = 1;
371         p_intf->p_sys->m_still_time = 1000000 * i_sec;
372     }
373     vlc_mutex_unlock( &p_intf->change_lock );
374
375     return VLC_SUCCESS;
376 }
377
378 /*****************************************************************************
379  * vcdIntfStillTime: function provided to reset still image
380  *****************************************************************************/
381 int vcdIntfResetStillTime( intf_thread_t *p_intf )
382 {
383     vlc_mutex_lock( &p_intf->change_lock );
384     p_intf->p_sys->m_still_time = 0;
385     var_SetInteger( p_intf->p_sys->p_input, "state", PLAYING_S );
386     vlc_mutex_unlock( &p_intf->change_lock );
387
388     return VLC_SUCCESS;
389 }