]> git.sesse.net Git - vlc/blob - src/input/var.c
3e722f4c11294353b712334c9cdff0260b69eae1
[vlc] / src / input / var.c
1 /*****************************************************************************
2  * var.c: object variables for input thread
3  *****************************************************************************
4  * Copyright (C) 2004-2007 VLC authors and VideoLAN
5  * $Id$
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8  *
9  * This program is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU Lesser General Public License as published by
11  * the Free Software Foundation; either version 2.1 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include <vlc_common.h>
32 #include <assert.h>
33 #include <math.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36
37 #include "input_internal.h"
38
39 /*****************************************************************************
40  * Callbacks
41  *****************************************************************************/
42 static int StateCallback   ( vlc_object_t *p_this, char const *psz_cmd,
43                              vlc_value_t oldval, vlc_value_t newval, void * );
44 static int RateCallback    ( vlc_object_t *p_this, char const *psz_cmd,
45                              vlc_value_t oldval, vlc_value_t newval, void * );
46 static int PositionCallback( vlc_object_t *p_this, char const *psz_cmd,
47                              vlc_value_t oldval, vlc_value_t newval, void * );
48 static int TimeCallback    ( vlc_object_t *p_this, char const *psz_cmd,
49                              vlc_value_t oldval, vlc_value_t newval, void * );
50 static int ProgramCallback ( vlc_object_t *p_this, char const *psz_cmd,
51                              vlc_value_t oldval, vlc_value_t newval, void * );
52 static int TitleCallback   ( vlc_object_t *p_this, char const *psz_cmd,
53                              vlc_value_t oldval, vlc_value_t newval, void * );
54 static int SeekpointCallback( vlc_object_t *p_this, char const *psz_cmd,
55                              vlc_value_t oldval, vlc_value_t newval, void * );
56 static int NavigationCallback( vlc_object_t *p_this, char const *psz_cmd,
57                              vlc_value_t oldval, vlc_value_t newval, void * );
58 static int ESCallback      ( vlc_object_t *p_this, char const *psz_cmd,
59                              vlc_value_t oldval, vlc_value_t newval, void * );
60 static int EsDelayCallback ( vlc_object_t *p_this, char const *psz_cmd,
61                              vlc_value_t oldval, vlc_value_t newval, void * );
62
63 static int BookmarkCallback( vlc_object_t *p_this, char const *psz_cmd,
64                              vlc_value_t oldval, vlc_value_t newval, void * );
65
66 static int RecordCallback( vlc_object_t *p_this, char const *psz_cmd,
67                            vlc_value_t oldval, vlc_value_t newval,
68                            void *p_data );
69 static int FrameNextCallback( vlc_object_t *p_this, char const *psz_cmd,
70                               vlc_value_t oldval, vlc_value_t newval,
71                               void *p_data );
72
73 typedef struct
74 {
75     const char *psz_name;
76     vlc_callback_t callback;
77 } vlc_input_callback_t;
78
79 static void InputAddCallbacks( input_thread_t *, const vlc_input_callback_t * );
80 static void InputDelCallbacks( input_thread_t *, const vlc_input_callback_t * );
81
82 #ifdef CALLBACK /* For windows */
83 # undef CALLBACK /* We don't care of this one here */
84 #endif
85 /* List all callbacks added by input */
86 #define CALLBACK(name,cb) { name, cb }
87 static const vlc_input_callback_t p_input_callbacks[] =
88 {
89     CALLBACK( "state", StateCallback ),
90     CALLBACK( "rate", RateCallback ),
91     CALLBACK( "position", PositionCallback ),
92     CALLBACK( "position-offset", PositionCallback ),
93     CALLBACK( "time", TimeCallback ),
94     CALLBACK( "time-offset", TimeCallback ),
95     CALLBACK( "bookmark", BookmarkCallback ),
96     CALLBACK( "program", ProgramCallback ),
97     CALLBACK( "title", TitleCallback ),
98     CALLBACK( "chapter", SeekpointCallback ),
99     CALLBACK( "audio-delay", EsDelayCallback ),
100     CALLBACK( "spu-delay", EsDelayCallback ),
101     CALLBACK( "video-es", ESCallback ),
102     CALLBACK( "audio-es", ESCallback ),
103     CALLBACK( "spu-es", ESCallback ),
104     CALLBACK( "record", RecordCallback ),
105     CALLBACK( "frame-next", FrameNextCallback ),
106
107     CALLBACK( NULL, NULL )
108 };
109 static const vlc_input_callback_t p_input_navigation_callbacks[] =
110 {
111     CALLBACK( "next-title", TitleCallback ),
112     CALLBACK( "prev-title", TitleCallback ),
113
114     CALLBACK( NULL, NULL )
115 };
116 static const vlc_input_callback_t p_input_title_callbacks[] =
117 {
118     CALLBACK( "next-chapter", SeekpointCallback ),
119     CALLBACK( "prev-chapter", SeekpointCallback ),
120
121     CALLBACK( NULL, NULL )
122 };
123 #undef CALLBACK
124
125 /*****************************************************************************
126  * input_ControlVarInit:
127  *  Create all control object variables with their callbacks
128  *****************************************************************************/
129 void input_ControlVarInit ( input_thread_t *p_input )
130 {
131     vlc_value_t val, text;
132
133     /* State */
134     var_Create( p_input, "state", VLC_VAR_INTEGER );
135     val.i_int = p_input->p->i_state;
136     var_Change( p_input, "state", VLC_VAR_SETVALUE, &val, NULL );
137
138     /* Rate */
139     var_Create( p_input, "rate", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT );
140
141     var_Create( p_input, "frame-next", VLC_VAR_VOID );
142
143     /* Position */
144     var_Create( p_input, "position",  VLC_VAR_FLOAT );
145     var_Create( p_input, "position-offset",  VLC_VAR_FLOAT );
146     val.f_float = 0.0;
147     var_Change( p_input, "position", VLC_VAR_SETVALUE, &val, NULL );
148
149     /* Time */
150     var_Create( p_input, "time",  VLC_VAR_TIME );
151     var_Create( p_input, "time-offset",  VLC_VAR_TIME );    /* relative */
152     val.i_time = 0;
153     var_Change( p_input, "time", VLC_VAR_SETVALUE, &val, NULL );
154
155     /* Bookmark */
156     var_Create( p_input, "bookmark", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE |
157                 VLC_VAR_ISCOMMAND );
158     val.psz_string = _("Bookmark");
159     var_Change( p_input, "bookmark", VLC_VAR_SETTEXT, &val, NULL );
160
161     /* Program */
162     var_Create( p_input, "program", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE |
163                 VLC_VAR_DOINHERIT );
164     var_Get( p_input, "program", &val );
165     if( val.i_int <= 0 )
166         var_Change( p_input, "program", VLC_VAR_DELCHOICE, &val, NULL );
167     text.psz_string = _("Program");
168     var_Change( p_input, "program", VLC_VAR_SETTEXT, &text, NULL );
169
170     /* Programs */
171     var_Create( p_input, "programs", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
172     text.psz_string = _("Programs");
173     var_Change( p_input, "programs", VLC_VAR_SETTEXT, &text, NULL );
174
175     /* Title */
176     var_Create( p_input, "title", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE );
177     text.psz_string = _("Title");
178     var_Change( p_input, "title", VLC_VAR_SETTEXT, &text, NULL );
179
180     /* Chapter */
181     var_Create( p_input, "chapter", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE );
182     text.psz_string = _("Chapter");
183     var_Change( p_input, "chapter", VLC_VAR_SETTEXT, &text, NULL );
184
185     /* Navigation The callback is added after */
186     var_Create( p_input, "navigation", VLC_VAR_VARIABLE | VLC_VAR_HASCHOICE );
187     text.psz_string = _("Navigation");
188     var_Change( p_input, "navigation", VLC_VAR_SETTEXT, &text, NULL );
189
190     /* Delay */
191     var_Create( p_input, "audio-delay", VLC_VAR_TIME );
192     val.i_time = INT64_C(1000) * var_GetInteger( p_input, "audio-desync" );
193     var_Change( p_input, "audio-delay", VLC_VAR_SETVALUE, &val, NULL );
194     var_Create( p_input, "spu-delay", VLC_VAR_TIME );
195     val.i_time = 0;
196     var_Change( p_input, "spu-delay", VLC_VAR_SETVALUE, &val, NULL );
197
198     /* Video ES */
199     var_Create( p_input, "video-es", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE );
200     text.psz_string = _("Video Track");
201     var_Change( p_input, "video-es", VLC_VAR_SETTEXT, &text, NULL );
202
203     /* Audio ES */
204     var_Create( p_input, "audio-es", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE );
205     text.psz_string = _("Audio Track");
206     var_Change( p_input, "audio-es", VLC_VAR_SETTEXT, &text, NULL );
207
208     /* Spu ES */
209     var_Create( p_input, "spu-es", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE );
210     text.psz_string = _("Subtitle Track");
211     var_Change( p_input, "spu-es", VLC_VAR_SETTEXT, &text, NULL );
212
213     /* Special read only objects variables for intf */
214     var_Create( p_input, "bookmarks", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
215
216     var_Create( p_input, "length",  VLC_VAR_TIME );
217     val.i_time = 0;
218     var_Change( p_input, "length", VLC_VAR_SETVALUE, &val, NULL );
219
220     var_Create( p_input, "bit-rate", VLC_VAR_INTEGER );
221     var_Create( p_input, "sample-rate", VLC_VAR_INTEGER );
222
223     if( !p_input->b_preparsing )
224     {
225         /* Special "intf-event" variable. */
226         var_Create( p_input, "intf-event", VLC_VAR_INTEGER );
227     }
228
229     /* Add all callbacks
230      * XXX we put callback only in non preparsing mode. We need to create the variable
231      * unless someone want to check all var_Get/var_Change return value ... */
232     if( !p_input->b_preparsing )
233         InputAddCallbacks( p_input, p_input_callbacks );
234 }
235
236 /*****************************************************************************
237  * input_ControlVarStop:
238  *****************************************************************************/
239 void input_ControlVarStop( input_thread_t *p_input )
240 {
241     if( !p_input->b_preparsing )
242         InputDelCallbacks( p_input, p_input_callbacks );
243
244     if( p_input->p->i_title > 0 )
245     {
246         char name[sizeof("title ") + 5 ];
247         int i;
248
249         InputDelCallbacks( p_input, p_input_navigation_callbacks );
250         InputDelCallbacks( p_input, p_input_title_callbacks );
251
252         for( i = 0; i < p_input->p->i_title; i++ )
253         {
254             snprintf( name, sizeof(name), "title %2i", i );
255             var_DelCallback( p_input, name, NavigationCallback, (void *)(intptr_t)i );
256         }
257     }
258 }
259
260 /*****************************************************************************
261  * input_ControlVarNavigation:
262  *  Create all remaining control object variables
263  *****************************************************************************/
264 void input_ControlVarNavigation( input_thread_t *p_input )
265 {
266     vlc_value_t val, text;
267     int  i;
268
269     /* Create more command variables */
270     if( p_input->p->i_title > 1 )
271     {
272         var_Create( p_input, "next-title", VLC_VAR_VOID );
273         text.psz_string = _("Next title");
274         var_Change( p_input, "next-title", VLC_VAR_SETTEXT, &text, NULL );
275         var_AddCallback( p_input, "next-title", TitleCallback, NULL );
276
277         var_Create( p_input, "prev-title", VLC_VAR_VOID );
278         text.psz_string = _("Previous title");
279         var_Change( p_input, "prev-title", VLC_VAR_SETTEXT, &text, NULL );
280         var_AddCallback( p_input, "prev-title", TitleCallback, NULL );
281     }
282
283     /* Create title and navigation */
284     val.psz_string = malloc( sizeof("title ") + 5 );
285     if( !val.psz_string )
286         return;
287
288     var_Change( p_input, "title", VLC_VAR_CLEARCHOICES, NULL, NULL );
289
290     for( i = 0; i < p_input->p->i_title; i++ )
291     {
292         vlc_value_t val2, text2;
293         int j;
294
295         /* Add Navigation entries */
296         sprintf( val.psz_string,  "title %2i", i );
297         var_Destroy( p_input, val.psz_string );
298         var_Create( p_input, val.psz_string,
299                     VLC_VAR_INTEGER|VLC_VAR_HASCHOICE|VLC_VAR_ISCOMMAND );
300         var_AddCallback( p_input, val.psz_string,
301                          NavigationCallback, (void *)(intptr_t)i );
302
303         char psz_length[MSTRTIME_MAX_SIZE + sizeof(" []")] = "";
304         if( p_input->p->title[i]->i_length > 0 )
305         {
306             strcpy( psz_length, " [" );
307             secstotimestr( &psz_length[2], p_input->p->title[i]->i_length / CLOCK_FREQ );
308             strcat( psz_length, "]" );
309         }
310
311         if( p_input->p->title[i]->psz_name == NULL ||
312             *p_input->p->title[i]->psz_name == '\0' )
313         {
314             if( asprintf( &text.psz_string, _("Title %i%s"),
315                           i + p_input->p->i_title_offset, psz_length ) == -1 )
316                 continue;
317         }
318         else
319         {
320             if( asprintf( &text.psz_string, "%s%s",
321                           p_input->p->title[i]->psz_name, psz_length ) == -1 )
322                 continue;
323         }
324         var_Change( p_input, "navigation", VLC_VAR_ADDCHOICE, &val, &text );
325
326         /* Add title choice */
327         val2.i_int = i;
328         var_Change( p_input, "title", VLC_VAR_ADDCHOICE, &val2, &text );
329
330         free( text.psz_string );
331
332         for( j = 0; j < p_input->p->title[i]->i_seekpoint; j++ )
333         {
334             val2.i_int = j;
335
336             if( p_input->p->title[i]->seekpoint[j]->psz_name == NULL ||
337                 *p_input->p->title[i]->seekpoint[j]->psz_name == '\0' )
338             {
339                 /* Default value */
340                 if( asprintf( &text2.psz_string, _("Chapter %i"),
341                           j + p_input->p->i_seekpoint_offset ) == -1 )
342                     continue;
343             }
344             else
345             {
346                 text2.psz_string =
347                     strdup( p_input->p->title[i]->seekpoint[j]->psz_name );
348             }
349
350             var_Change( p_input, val.psz_string, VLC_VAR_ADDCHOICE,
351                         &val2, &text2 );
352             free( text2.psz_string );
353         }
354
355     }
356     free( val.psz_string );
357 }
358
359 /*****************************************************************************
360  * input_ControlVarTitle:
361  *  Create all variables for a title
362  *****************************************************************************/
363 void input_ControlVarTitle( input_thread_t *p_input, int i_title )
364 {
365     input_title_t *t = p_input->p->title[i_title];
366     vlc_value_t text;
367     int  i;
368
369     /* Create/Destroy command variables */
370     if( t->i_seekpoint <= 1 )
371     {
372         var_Destroy( p_input, "next-chapter" );
373         var_Destroy( p_input, "prev-chapter" );
374     }
375     else if( var_Type( p_input, "next-chapter" ) == 0 )
376     {
377         var_Create( p_input, "next-chapter", VLC_VAR_VOID );
378         text.psz_string = _("Next chapter");
379         var_Change( p_input, "next-chapter", VLC_VAR_SETTEXT, &text, NULL );
380         var_AddCallback( p_input, "next-chapter", SeekpointCallback, NULL );
381
382         var_Create( p_input, "prev-chapter", VLC_VAR_VOID );
383         text.psz_string = _("Previous chapter");
384         var_Change( p_input, "prev-chapter", VLC_VAR_SETTEXT, &text, NULL );
385         var_AddCallback( p_input, "prev-chapter", SeekpointCallback, NULL );
386     }
387
388     /* Build chapter list */
389     var_Change( p_input, "chapter", VLC_VAR_CLEARCHOICES, NULL, NULL );
390     for( i = 0; i <  t->i_seekpoint; i++ )
391     {
392         vlc_value_t val;
393         val.i_int = i;
394
395         if( t->seekpoint[i]->psz_name == NULL ||
396             *t->seekpoint[i]->psz_name == '\0' )
397         {
398             /* Default value */
399             if( asprintf( &text.psz_string, _("Chapter %i"),
400                       i + p_input->p->i_seekpoint_offset ) == -1 )
401                 continue;
402         }
403         else
404         {
405             text.psz_string = strdup( t->seekpoint[i]->psz_name );
406         }
407
408         var_Change( p_input, "chapter", VLC_VAR_ADDCHOICE, &val, &text );
409         free( text.psz_string );
410     }
411 }
412
413 /*****************************************************************************
414  * input_ConfigVarInit:
415  *  Create all config object variables
416  *****************************************************************************/
417 void input_ConfigVarInit ( input_thread_t *p_input )
418 {
419     /* Create Object Variables for private use only */
420
421     if( !p_input->b_preparsing )
422     {
423         var_Create( p_input, "video", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
424         var_Create( p_input, "audio", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
425         var_Create( p_input, "spu", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
426
427         var_Create( p_input, "audio-track", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
428         var_Create( p_input, "sub-track", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
429
430         var_Create( p_input, "audio-language",
431                     VLC_VAR_STRING|VLC_VAR_DOINHERIT );
432         var_Create( p_input, "sub-language",
433                     VLC_VAR_STRING|VLC_VAR_DOINHERIT );
434         var_Create( p_input, "menu-language",
435                     VLC_VAR_STRING|VLC_VAR_DOINHERIT );
436
437         var_Create( p_input, "audio-track-id",
438                     VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
439         var_Create( p_input, "sub-track-id",
440                     VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
441
442         var_Create( p_input, "sub-file", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
443         var_Create( p_input, "sub-autodetect-file", VLC_VAR_BOOL |
444                     VLC_VAR_DOINHERIT );
445         var_Create( p_input, "sub-autodetect-path", VLC_VAR_STRING |
446                     VLC_VAR_DOINHERIT );
447         var_Create( p_input, "sub-autodetect-fuzzy", VLC_VAR_INTEGER |
448                     VLC_VAR_DOINHERIT );
449
450         var_Create( p_input, "sout", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
451         var_Create( p_input, "sout-all",   VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
452         var_Create( p_input, "sout-audio", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
453         var_Create( p_input, "sout-video", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
454         var_Create( p_input, "sout-spu", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
455         var_Create( p_input, "sout-keep",  VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
456
457         var_Create( p_input, "input-repeat",
458                     VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
459         var_Create( p_input, "start-time", VLC_VAR_FLOAT|VLC_VAR_DOINHERIT );
460         var_Create( p_input, "stop-time", VLC_VAR_FLOAT|VLC_VAR_DOINHERIT );
461         var_Create( p_input, "run-time", VLC_VAR_FLOAT|VLC_VAR_DOINHERIT );
462         var_Create( p_input, "input-fast-seek", VLC_VAR_BOOL|VLC_VAR_DOINHERIT );
463
464         var_Create( p_input, "input-slave",
465                     VLC_VAR_STRING | VLC_VAR_DOINHERIT );
466
467         var_Create( p_input, "audio-desync",
468                     VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
469         var_Create( p_input, "cr-average",
470                     VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
471         var_Create( p_input, "clock-synchro",
472                     VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
473     }
474
475     var_Create( p_input, "can-seek", VLC_VAR_BOOL );
476     var_SetBool( p_input, "can-seek", true ); /* Fixed later*/
477
478     var_Create( p_input, "can-pause", VLC_VAR_BOOL );
479     var_SetBool( p_input, "can-pause", true ); /* Fixed later*/
480
481     var_Create( p_input, "can-rate", VLC_VAR_BOOL );
482     var_SetBool( p_input, "can-rate", false );
483
484     var_Create( p_input, "can-rewind", VLC_VAR_BOOL );
485     var_SetBool( p_input, "can-rewind", false );
486
487     var_Create( p_input, "can-record", VLC_VAR_BOOL );
488     var_SetBool( p_input, "can-record", false ); /* Fixed later*/
489
490     var_Create( p_input, "record", VLC_VAR_BOOL );
491     var_SetBool( p_input, "record", false );
492
493     var_Create( p_input, "teletext-es", VLC_VAR_INTEGER );
494     var_SetInteger( p_input, "teletext-es", -1 );
495
496     var_Create( p_input, "signal-quality", VLC_VAR_FLOAT );
497     var_SetFloat( p_input, "signal-quality", -1 );
498
499     var_Create( p_input, "signal-strength", VLC_VAR_FLOAT );
500     var_SetFloat( p_input, "signal-strength", -1 );
501
502     var_Create( p_input, "program-scrambled", VLC_VAR_BOOL );
503     var_SetBool( p_input, "program-scrambled", false );
504
505     var_Create( p_input, "cache", VLC_VAR_FLOAT );
506     var_SetFloat( p_input, "cache", 0.0 );
507
508     /* */
509     var_Create( p_input, "input-record-native", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
510
511     /* */
512     var_Create( p_input, "access", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
513     var_Create( p_input, "demux", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
514     var_Create( p_input, "stream-filter", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
515
516     /* Meta */
517     var_Create( p_input, "meta-title", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
518     var_Create( p_input, "meta-author", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
519     var_Create( p_input, "meta-artist", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
520     var_Create( p_input, "meta-genre", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
521     var_Create( p_input, "meta-copyright", VLC_VAR_STRING | VLC_VAR_DOINHERIT);
522     var_Create( p_input, "meta-description", VLC_VAR_STRING|VLC_VAR_DOINHERIT);
523     var_Create( p_input, "meta-date", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
524     var_Create( p_input, "meta-url", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
525 }
526
527 /*****************************************************************************
528  * Callbacks managements:
529  *****************************************************************************/
530 static void InputAddCallbacks( input_thread_t *p_input,
531                                const vlc_input_callback_t *p_callbacks )
532 {
533     int i;
534     for( i = 0; p_callbacks[i].psz_name != NULL; i++ )
535         var_AddCallback( p_input,
536                          p_callbacks[i].psz_name,
537                          p_callbacks[i].callback, NULL );
538 }
539
540 static void InputDelCallbacks( input_thread_t *p_input,
541                                const vlc_input_callback_t *p_callbacks )
542 {
543     int i;
544     for( i = 0; p_callbacks[i].psz_name != NULL; i++ )
545         var_DelCallback( p_input,
546                          p_callbacks[i].psz_name,
547                          p_callbacks[i].callback, NULL );
548 }
549
550 /*****************************************************************************
551  * All Callbacks:
552  *****************************************************************************/
553 static int StateCallback( vlc_object_t *p_this, char const *psz_cmd,
554                           vlc_value_t oldval, vlc_value_t newval,
555                           void *p_data )
556 {
557     input_thread_t *p_input = (input_thread_t*)p_this;
558     VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval); VLC_UNUSED(p_data);
559
560     if( newval.i_int == PLAYING_S || newval.i_int == PAUSE_S )
561     {
562         input_ControlPush( p_input, INPUT_CONTROL_SET_STATE, &newval );
563         return VLC_SUCCESS;
564     }
565
566     return VLC_EGENERIC;
567 }
568
569 static int RateCallback( vlc_object_t *p_this, char const *psz_cmd,
570                          vlc_value_t oldval, vlc_value_t newval, void *p_data )
571 {
572     input_thread_t *p_input = (input_thread_t*)p_this;
573     VLC_UNUSED(oldval); VLC_UNUSED(p_data); VLC_UNUSED(psz_cmd);
574
575     newval.i_int = INPUT_RATE_DEFAULT / newval.f_float;
576     input_ControlPush( p_input, INPUT_CONTROL_SET_RATE, &newval );
577
578     return VLC_SUCCESS;
579 }
580
581 static int PositionCallback( vlc_object_t *p_this, char const *psz_cmd,
582                              vlc_value_t oldval, vlc_value_t newval,
583                              void *p_data )
584 {
585     input_thread_t *p_input = (input_thread_t*)p_this;
586     VLC_UNUSED(oldval); VLC_UNUSED(p_data);
587
588     if( !strcmp( psz_cmd, "position-offset" ) )
589     {
590         float f_position = var_GetFloat( p_input, "position" ) + newval.f_float;
591         if( f_position < 0.0 )
592             f_position = 0.0;
593         else if( f_position > 1.0 )
594             f_position = 1.0;
595         var_SetFloat( p_this, "position", f_position );
596     }
597     else
598     {
599         /* Update "length" for better intf behavour */
600         const mtime_t i_length = var_GetTime( p_input, "length" );
601         if( i_length > 0 && newval.f_float >= 0.0 && newval.f_float <= 1.0 )
602         {
603             vlc_value_t val;
604
605             val.i_time = i_length * newval.f_float;
606             var_Change( p_input, "time", VLC_VAR_SETVALUE, &val, NULL );
607         }
608
609         /* */
610         input_ControlPush( p_input, INPUT_CONTROL_SET_POSITION, &newval );
611     }
612     return VLC_SUCCESS;
613 }
614
615 static int TimeCallback( vlc_object_t *p_this, char const *psz_cmd,
616                          vlc_value_t oldval, vlc_value_t newval, void *p_data )
617 {
618     input_thread_t *p_input = (input_thread_t*)p_this;
619     VLC_UNUSED(oldval); VLC_UNUSED(p_data);
620
621     if( !strcmp( psz_cmd, "time-offset" ) )
622     {
623         mtime_t i_time = var_GetTime( p_input, "time" ) + newval.i_time;
624         if( i_time < 0 )
625             i_time = 0;
626         var_SetTime( p_this, "time", i_time );
627     }
628     else
629     {
630         /* Update "position" for better intf behavour */
631         const mtime_t i_length = var_GetTime( p_input, "length" );
632         if( i_length > 0 && newval.i_time >= 0 && newval.i_time <= i_length )
633         {
634             vlc_value_t val;
635
636             val.f_float = (double)newval.i_time/(double)i_length;
637             var_Change( p_input, "position", VLC_VAR_SETVALUE, &val, NULL );
638             /*
639              * Notify the intf that a new event has been occurred.
640              * XXX this is a bit hackish but it's the only way to do it now.
641              */
642             var_SetInteger( p_input, "intf-event", INPUT_EVENT_POSITION );
643         }
644
645         /* */
646         input_ControlPush( p_input, INPUT_CONTROL_SET_TIME, &newval );
647     }
648     return VLC_SUCCESS;
649 }
650
651 static int ProgramCallback( vlc_object_t *p_this, char const *psz_cmd,
652                             vlc_value_t oldval, vlc_value_t newval,
653                             void *p_data )
654 {
655     input_thread_t *p_input = (input_thread_t*)p_this;
656     VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval); VLC_UNUSED(p_data);
657
658     input_ControlPush( p_input, INPUT_CONTROL_SET_PROGRAM, &newval );
659
660     return VLC_SUCCESS;
661 }
662
663 static int TitleCallback( vlc_object_t *p_this, char const *psz_cmd,
664                           vlc_value_t oldval, vlc_value_t newval,
665                           void *p_data )
666 {
667     input_thread_t *p_input = (input_thread_t*)p_this;
668     vlc_value_t val, count;
669     VLC_UNUSED(oldval); VLC_UNUSED(p_data);
670
671     if( !strcmp( psz_cmd, "next-title" ) )
672     {
673         input_ControlPush( p_input, INPUT_CONTROL_SET_TITLE_NEXT, NULL );
674
675         val.i_int = var_GetInteger( p_input, "title" ) + 1;
676         var_Change( p_input, "title", VLC_VAR_CHOICESCOUNT, &count, NULL );
677         if( val.i_int < count.i_int )
678             var_Change( p_input, "title", VLC_VAR_SETVALUE, &val, NULL );
679     }
680     else if( !strcmp( psz_cmd, "prev-title" ) )
681     {
682         input_ControlPush( p_input, INPUT_CONTROL_SET_TITLE_PREV, NULL );
683
684         val.i_int = var_GetInteger( p_input, "title" ) - 1;
685         if( val.i_int >= 0 )
686             var_Change( p_input, "title", VLC_VAR_SETVALUE, &val, NULL );
687     }
688     else
689     {
690         input_ControlPush( p_input, INPUT_CONTROL_SET_TITLE, &newval );
691     }
692
693     return VLC_SUCCESS;
694 }
695
696 static int SeekpointCallback( vlc_object_t *p_this, char const *psz_cmd,
697                               vlc_value_t oldval, vlc_value_t newval,
698                               void *p_data )
699 {
700     input_thread_t *p_input = (input_thread_t*)p_this;
701     vlc_value_t val, count;
702     VLC_UNUSED(oldval); VLC_UNUSED(p_data);
703
704     if( !strcmp( psz_cmd, "next-chapter" ) )
705     {
706         input_ControlPush( p_input, INPUT_CONTROL_SET_SEEKPOINT_NEXT, NULL );
707
708         val.i_int = var_GetInteger( p_input, "chapter" ) + 1;
709         var_Change( p_input, "chapter", VLC_VAR_CHOICESCOUNT, &count, NULL );
710         if( val.i_int < count.i_int )
711             var_Change( p_input, "chapter", VLC_VAR_SETVALUE, &val, NULL );
712     }
713     else if( !strcmp( psz_cmd, "prev-chapter" ) )
714     {
715         input_ControlPush( p_input, INPUT_CONTROL_SET_SEEKPOINT_PREV, NULL );
716
717         val.i_int = var_GetInteger( p_input, "chapter" ) - 1;
718         if( val.i_int >= 0 )
719             var_Change( p_input, "chapter", VLC_VAR_SETVALUE, &val, NULL );
720     }
721     else
722     {
723         input_ControlPush( p_input, INPUT_CONTROL_SET_SEEKPOINT, &newval );
724     }
725
726     return VLC_SUCCESS;
727 }
728
729 static int NavigationCallback( vlc_object_t *p_this, char const *psz_cmd,
730                                vlc_value_t oldval, vlc_value_t newval,
731                                void *p_data )
732 {
733     input_thread_t *p_input = (input_thread_t*)p_this;
734     vlc_value_t     val;
735     VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval);
736
737     /* Issue a title change */
738     val.i_int = (intptr_t)p_data;
739     input_ControlPush( p_input, INPUT_CONTROL_SET_TITLE, &val );
740
741     var_Change( p_input, "title", VLC_VAR_SETVALUE, &val, NULL );
742
743     /* And a chapter change */
744     input_ControlPush( p_input, INPUT_CONTROL_SET_SEEKPOINT, &newval );
745
746     var_Change( p_input, "chapter", VLC_VAR_SETVALUE, &newval, NULL );
747
748     return VLC_SUCCESS;
749 }
750
751 static int ESCallback( vlc_object_t *p_this, char const *psz_cmd,
752                        vlc_value_t oldval, vlc_value_t newval, void *p_data )
753 {
754     input_thread_t *p_input = (input_thread_t*)p_this;
755     VLC_UNUSED(oldval); VLC_UNUSED(p_data);
756
757     if( newval.i_int < 0 )
758     {
759         vlc_value_t v;
760         /* Hack */
761         if( !strcmp( psz_cmd, "audio-es" ) )
762             v.i_int = -AUDIO_ES;
763         else if( !strcmp( psz_cmd, "video-es" ) )
764             v.i_int = -VIDEO_ES;
765         else if( !strcmp( psz_cmd, "spu-es" ) )
766             v.i_int = -SPU_ES;
767         else
768             v.i_int = 0;
769         if( v.i_int != 0 )
770             input_ControlPush( p_input, INPUT_CONTROL_SET_ES, &v );
771     }
772     else
773     {
774         input_ControlPush( p_input, INPUT_CONTROL_SET_ES, &newval );
775     }
776
777     return VLC_SUCCESS;
778 }
779
780 static int EsDelayCallback ( vlc_object_t *p_this, char const *psz_cmd,
781                              vlc_value_t oldval, vlc_value_t newval, void *p_data )
782 {
783     input_thread_t *p_input = (input_thread_t*)p_this;
784     VLC_UNUSED(oldval); VLC_UNUSED(p_data);
785
786     if( !strcmp( psz_cmd, "audio-delay" ) )
787     {
788         input_ControlPush( p_input, INPUT_CONTROL_SET_AUDIO_DELAY, &newval );
789     }
790     else if( !strcmp( psz_cmd, "spu-delay" ) )
791     {
792         input_ControlPush( p_input, INPUT_CONTROL_SET_SPU_DELAY, &newval );
793     }
794     return VLC_SUCCESS;
795 }
796
797 static int BookmarkCallback( vlc_object_t *p_this, char const *psz_cmd,
798                              vlc_value_t oldval, vlc_value_t newval,
799                              void *p_data )
800 {
801     input_thread_t *p_input = (input_thread_t*)p_this;
802     VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval); VLC_UNUSED(p_data);
803
804     input_ControlPush( p_input, INPUT_CONTROL_SET_BOOKMARK, &newval );
805
806     return VLC_SUCCESS;
807 }
808
809 static int RecordCallback( vlc_object_t *p_this, char const *psz_cmd,
810                            vlc_value_t oldval, vlc_value_t newval,
811                            void *p_data )
812 {
813     input_thread_t *p_input = (input_thread_t*)p_this;
814     VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval); VLC_UNUSED(p_data);
815
816     input_ControlPush( p_input, INPUT_CONTROL_SET_RECORD_STATE, &newval );
817
818     return VLC_SUCCESS;
819 }
820
821 static int FrameNextCallback( vlc_object_t *p_this, char const *psz_cmd,
822                               vlc_value_t oldval, vlc_value_t newval,
823                               void *p_data )
824 {
825     input_thread_t *p_input = (input_thread_t*)p_this;
826     VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval); VLC_UNUSED(p_data);
827     VLC_UNUSED(newval);
828
829     input_ControlPush( p_input, INPUT_CONTROL_SET_FRAME_NEXT, NULL );
830
831     return VLC_SUCCESS;
832 }
833