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