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