input: fix |/& typo
[vlc.git] / src / input / var.c
blobc35bd40ba24262d91aafbeffacbab8dce0bb1540
1 /*****************************************************************************
2 * var.c: object variables for input thread
3 *****************************************************************************
4 * Copyright (C) 2004-2007 VLC authors and VideoLAN
5 * $Id$
7 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
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.
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.
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 *****************************************************************************/
24 /*****************************************************************************
25 * Preamble
26 *****************************************************************************/
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
31 #include <vlc_common.h>
32 #include <vlc_memstream.h>
33 #include <assert.h>
34 #include <math.h>
35 #include <stdio.h>
36 #include <stdlib.h>
38 #include "input_internal.h"
40 /*****************************************************************************
41 * Callbacks
42 *****************************************************************************/
43 static int StateCallback ( vlc_object_t *p_this, char const *psz_cmd,
44 vlc_value_t oldval, vlc_value_t newval, void * );
45 static int RateCallback ( vlc_object_t *p_this, char const *psz_cmd,
46 vlc_value_t oldval, vlc_value_t newval, void * );
47 static int PositionCallback( vlc_object_t *p_this, char const *psz_cmd,
48 vlc_value_t oldval, vlc_value_t newval, void * );
49 static int TimeCallback ( vlc_object_t *p_this, char const *psz_cmd,
50 vlc_value_t oldval, vlc_value_t newval, void * );
51 static int TimeOffsetCallback( vlc_object_t *p_this, char const *psz_cmd,
52 vlc_value_t oldval, vlc_value_t newval, void * );
53 static int ProgramCallback ( vlc_object_t *p_this, char const *psz_cmd,
54 vlc_value_t oldval, vlc_value_t newval, void * );
55 static int TitleCallback ( vlc_object_t *p_this, char const *psz_cmd,
56 vlc_value_t oldval, vlc_value_t newval, void * );
57 static int SeekpointCallback( vlc_object_t *p_this, char const *psz_cmd,
58 vlc_value_t oldval, vlc_value_t newval, void * );
59 static int NavigationCallback( vlc_object_t *p_this, char const *psz_cmd,
60 vlc_value_t oldval, vlc_value_t newval, void * );
61 static int EsVideoCallback ( vlc_object_t *p_this, char const *psz_cmd,
62 vlc_value_t oldval, vlc_value_t newval, void * );
63 static int EsAudioCallback ( vlc_object_t *p_this, char const *psz_cmd,
64 vlc_value_t oldval, vlc_value_t newval, void * );
65 static int EsSpuCallback ( vlc_object_t *p_this, char const *psz_cmd,
66 vlc_value_t oldval, vlc_value_t newval, void * );
67 static int EsDelayCallback ( vlc_object_t *p_this, char const *psz_cmd,
68 vlc_value_t oldval, vlc_value_t newval, void * );
70 static int BookmarkCallback( vlc_object_t *p_this, char const *psz_cmd,
71 vlc_value_t oldval, vlc_value_t newval, void * );
73 static int RecordCallback( vlc_object_t *p_this, char const *psz_cmd,
74 vlc_value_t oldval, vlc_value_t newval,
75 void *p_data );
76 static int FrameNextCallback( vlc_object_t *p_this, char const *psz_cmd,
77 vlc_value_t oldval, vlc_value_t newval,
78 void *p_data );
79 static void input_LegacyVarTitle( input_thread_t *p_input, int i_title );
80 static void input_LegacyVarNavigation( input_thread_t *p_input );
82 typedef struct
84 const char *psz_name;
85 vlc_callback_t callback;
86 } vlc_input_callback_t;
88 static void InputAddCallbacks( input_thread_t *, const vlc_input_callback_t * );
89 static void InputDelCallbacks( input_thread_t *, const vlc_input_callback_t * );
91 #ifdef CALLBACK /* For windows */
92 # undef CALLBACK /* We don't care of this one here */
93 #endif
94 /* List all callbacks added by input */
95 #define CALLBACK(name,cb) { name, cb }
96 static const vlc_input_callback_t p_input_callbacks[] =
98 CALLBACK( "state", StateCallback ),
99 CALLBACK( "rate", RateCallback ),
100 CALLBACK( "position", PositionCallback ),
101 CALLBACK( "time", TimeCallback ),
102 CALLBACK( "time-offset", TimeOffsetCallback ),
103 CALLBACK( "bookmark", BookmarkCallback ),
104 CALLBACK( "program", ProgramCallback ),
105 CALLBACK( "title", TitleCallback ),
106 CALLBACK( "chapter", SeekpointCallback ),
107 CALLBACK( "audio-delay", EsDelayCallback ),
108 CALLBACK( "spu-delay", EsDelayCallback ),
109 CALLBACK( "video-es", EsVideoCallback ),
110 CALLBACK( "audio-es", EsAudioCallback ),
111 CALLBACK( "spu-es", EsSpuCallback ),
112 CALLBACK( "record", RecordCallback ),
113 CALLBACK( "frame-next", FrameNextCallback ),
115 CALLBACK( NULL, NULL )
117 #undef CALLBACK
119 static void Trigger( input_thread_t *p_input, int i_type )
121 var_SetInteger( p_input, "intf-event", i_type );
123 static void VarListAdd( input_thread_t *p_input,
124 const char *psz_variable, int i_event,
125 int i_value, const char *psz_text )
127 vlc_value_t val;
129 val.i_int = i_value;
131 var_Change( p_input, psz_variable, VLC_VAR_ADDCHOICE, val, psz_text );
133 Trigger( p_input, i_event );
135 static void VarListDel( input_thread_t *p_input,
136 const char *psz_variable, int i_event,
137 int i_value )
139 vlc_value_t val;
141 if( i_value >= 0 )
143 val.i_int = i_value;
144 var_Change( p_input, psz_variable, VLC_VAR_DELCHOICE, val );
146 else
148 var_Change( p_input, psz_variable, VLC_VAR_CLEARCHOICES );
151 Trigger( p_input, i_event );
153 static void VarListSelect( input_thread_t *p_input,
154 const char *psz_variable, int i_event,
155 int i_value )
157 vlc_value_t val;
159 val.i_int = i_value;
160 var_Change( p_input, psz_variable, VLC_VAR_SETVALUE, val );
162 Trigger( p_input, i_event );
164 static const char *GetEsVarName( enum es_format_category_e i_cat )
166 switch( i_cat )
168 case VIDEO_ES:
169 return "video-es";
170 case AUDIO_ES:
171 return "audio-es";
172 case SPU_ES:
173 return "spu-es";
174 default:
175 return NULL;
179 static void UpdateBookmarksOption( input_thread_t *p_input )
181 input_thread_private_t *priv = input_priv(p_input);
182 struct vlc_memstream vstr;
184 vlc_memstream_open( &vstr );
185 vlc_memstream_puts( &vstr, "bookmarks=" );
187 vlc_mutex_lock( &priv->p_item->lock );
188 var_Change( p_input, "bookmark", VLC_VAR_CLEARCHOICES );
190 for( int i = 0; i < priv->i_bookmark; i++ )
192 seekpoint_t const* sp = priv->pp_bookmark[i];
194 /* Add bookmark to choice-list */
195 var_Change( p_input, "bookmark", VLC_VAR_ADDCHOICE,
196 (vlc_value_t){ .i_int = i }, sp->psz_name );
198 /* Append bookmark to option-buffer */
199 /* TODO: escape inappropriate values */
200 vlc_memstream_printf( &vstr, "%s{name=%s,time=%.3f}",
201 i > 0 ? "," : "", sp->psz_name, ( 1. * sp->i_time_offset ) / CLOCK_FREQ );
204 vlc_mutex_unlock( &priv->p_item->lock );
206 if( vlc_memstream_close( &vstr ) == VLC_SUCCESS )
208 bool b_overwritten = false;
210 for( int i = 0; i < priv->p_item->i_options; ++i )
212 char** ppsz_option = &priv->p_item->ppsz_options[i];
214 if( strncmp( *ppsz_option, "bookmarks=", 10 ) == 0 )
216 free( *ppsz_option );
217 *ppsz_option = vstr.ptr;
218 b_overwritten = true;
222 if( !b_overwritten )
224 input_item_AddOption( priv->p_item, vstr.ptr,
225 VLC_INPUT_OPTION_UNIQUE );
226 free( vstr.ptr );
231 void input_LegacyEvents( input_thread_t *p_input, void *user_data,
232 const struct vlc_input_event *event )
234 (void) user_data;
235 vlc_value_t val;
237 switch( event->type )
239 case INPUT_EVENT_STATE:
240 val.i_int = event->state;
241 var_Change( p_input, "state", VLC_VAR_SETVALUE, val );
242 break;
243 case INPUT_EVENT_DEAD:
244 break;
245 case INPUT_EVENT_RATE:
246 val.f_float = event->rate;
247 var_Change( p_input, "rate", VLC_VAR_SETVALUE, val );
248 break;
249 case INPUT_EVENT_CAPABILITIES:
250 var_SetBool( p_input, "can-seek",
251 event->capabilities & VLC_INPUT_CAPABILITIES_SEEKABLE );
252 var_SetBool( p_input, "can-pause",
253 event->capabilities & VLC_INPUT_CAPABILITIES_PAUSEABLE );
254 var_SetBool( p_input, "can-rate",
255 event->capabilities & VLC_INPUT_CAPABILITIES_CHANGE_RATE );
256 var_SetBool( p_input, "can-rewind",
257 event->capabilities & VLC_INPUT_CAPABILITIES_REWINDABLE );
258 var_SetBool( p_input, "can-record",
259 event->capabilities & VLC_INPUT_CAPABILITIES_RECORDABLE );
260 break;
261 case INPUT_EVENT_POSITION:
262 val.f_float = event->position.percentage;
263 var_Change( p_input, "position", VLC_VAR_SETVALUE, val );
264 val.i_int = event->position.ms;
265 var_Change( p_input, "time", VLC_VAR_SETVALUE, val );
266 break;
267 case INPUT_EVENT_LENGTH:
268 /* FIXME ugly + what about meta change event ? */
269 if( var_GetInteger( p_input, "length" ) == event->length )
270 return;
271 val.i_int = event->length;
272 var_Change( p_input, "length", VLC_VAR_SETVALUE, val );
273 break;
274 case INPUT_EVENT_TITLE:
275 val.i_int = event->title;
276 var_Change( p_input, "title", VLC_VAR_SETVALUE, val );
277 input_LegacyVarNavigation( p_input );
278 input_LegacyVarTitle( p_input, event->title );
279 break;
280 case INPUT_EVENT_CHAPTER:
281 /* "chapter" */
282 val.i_int = event->chapter.seekpoint;
283 var_Change( p_input, "chapter", VLC_VAR_SETVALUE, val );
285 /* "title %2u" */
286 char psz_title[sizeof ("title ") + 3 * sizeof (int)];
287 sprintf( psz_title, "title %2u", event->chapter.title );
288 var_Change( p_input, psz_title, VLC_VAR_SETVALUE, val );
289 break;
290 case INPUT_EVENT_PROGRAM:
291 switch (event->program.action)
293 case VLC_INPUT_PROGRAM_ADDED:
294 VarListAdd( p_input, "program", INPUT_EVENT_PROGRAM,
295 event->program.id, event->program.title );
296 break;
297 case VLC_INPUT_PROGRAM_DELETED:
298 VarListDel( p_input, "program", INPUT_EVENT_PROGRAM,
299 event->program.id );
300 break;
301 case VLC_INPUT_PROGRAM_SELECTED:
302 VarListSelect( p_input, "program", INPUT_EVENT_PROGRAM,
303 event->program.id );
304 break;
305 case VLC_INPUT_PROGRAM_SCRAMBLED:
306 if( var_GetInteger( p_input, "program" ) != event->program.id )
307 return;
308 var_SetBool( p_input, "program-scrambled", event->program.scrambled );
309 break;
311 break;
312 case INPUT_EVENT_ES:
313 switch (event->es.action)
315 case VLC_INPUT_ES_ADDED:
317 const char *varname = GetEsVarName( event->es.cat );
318 if( varname )
319 VarListAdd( p_input, varname, INPUT_EVENT_ES,
320 event->es.id, event->es.title );
321 break;
323 case VLC_INPUT_ES_DELETED:
325 const char *varname = GetEsVarName( event->es.cat );
326 if( varname )
327 VarListDel( p_input, varname, INPUT_EVENT_ES,
328 event->es.id );
329 break;
331 case VLC_INPUT_ES_SELECTED:
333 const char *varname = GetEsVarName( event->es.cat );
334 if( varname )
335 VarListSelect( p_input, varname, INPUT_EVENT_ES,
336 event->es.id );
337 break;
340 break;
341 case INPUT_EVENT_TELETEXT:
342 switch (event->teletext.action)
344 case VLC_INPUT_TELETEXT_ADDED:
345 VarListAdd( p_input, "teletext-es", INPUT_EVENT_TELETEXT,
346 event->teletext.id, event->teletext.title );
347 break;
348 case VLC_INPUT_TELETEXT_DELETED:
349 VarListDel( p_input, "teletext-es", INPUT_EVENT_TELETEXT,
350 event->teletext.id );
351 break;
352 case VLC_INPUT_TELETEXT_SELECTED:
353 VarListSelect( p_input, "teletext-es", INPUT_EVENT_TELETEXT,
354 event->teletext.id );
355 break;
357 break;
358 case INPUT_EVENT_RECORD:
359 val.b_bool = event->record;
360 var_Change( p_input, "record", VLC_VAR_SETVALUE, val );
361 break;
362 case INPUT_EVENT_ITEM_META:
363 break;
364 case INPUT_EVENT_ITEM_INFO:
365 break;
366 case INPUT_EVENT_ITEM_EPG:
367 break;
368 case INPUT_EVENT_STATISTICS:
369 break;
370 case INPUT_EVENT_SIGNAL:
371 val.f_float = event->signal.quality;
372 var_Change( p_input, "signal-quality", VLC_VAR_SETVALUE, val );
373 val.f_float = event->signal.strength;
374 var_Change( p_input, "signal-strength", VLC_VAR_SETVALUE, val );
375 break;
376 case INPUT_EVENT_AUDIO_DELAY:
377 val.i_int = event->audio_delay;
378 var_Change( p_input, "audio-delay", VLC_VAR_SETVALUE, val );
379 break;
380 case INPUT_EVENT_SUBTITLE_DELAY:
381 val.i_int = event->subtitle_delay;
382 var_Change( p_input, "spu-delay", VLC_VAR_SETVALUE, val );
383 break;
384 case INPUT_EVENT_BOOKMARK:
385 UpdateBookmarksOption( p_input );
386 break;
387 case INPUT_EVENT_CACHE:
388 val.f_float = event->cache;
389 var_Change( p_input, "cache", VLC_VAR_SETVALUE, val );
390 break;
391 case INPUT_EVENT_AOUT:
392 break;
393 case INPUT_EVENT_VOUT:
394 break;
396 Trigger( p_input, event->type );
399 /*****************************************************************************
400 * input_LegacyVarInit:
401 * Create all control object variables with their callbacks
402 *****************************************************************************/
403 void input_LegacyVarInit ( input_thread_t *p_input )
405 vlc_value_t val;
407 var_Create( p_input, "can-seek", VLC_VAR_BOOL );
408 var_SetBool( p_input, "can-seek", true ); /* Fixed later*/
410 var_Create( p_input, "can-pause", VLC_VAR_BOOL );
411 var_SetBool( p_input, "can-pause", true ); /* Fixed later*/
413 var_Create( p_input, "can-rate", VLC_VAR_BOOL );
414 var_SetBool( p_input, "can-rate", false );
416 var_Create( p_input, "can-rewind", VLC_VAR_BOOL );
417 var_SetBool( p_input, "can-rewind", false );
419 var_Create( p_input, "can-record", VLC_VAR_BOOL );
420 var_SetBool( p_input, "can-record", false ); /* Fixed later*/
422 var_Create( p_input, "record", VLC_VAR_BOOL );
423 var_SetBool( p_input, "record", false );
425 var_Create( p_input, "teletext-es", VLC_VAR_INTEGER );
426 var_SetInteger( p_input, "teletext-es", -1 );
428 var_Create( p_input, "cache", VLC_VAR_FLOAT );
429 var_SetFloat( p_input, "cache", 0.0 );
431 var_Create( p_input, "signal-quality", VLC_VAR_FLOAT );
432 var_SetFloat( p_input, "signal-quality", -1 );
434 var_Create( p_input, "signal-strength", VLC_VAR_FLOAT );
435 var_SetFloat( p_input, "signal-strength", -1 );
437 var_Create( p_input, "program-scrambled", VLC_VAR_BOOL );
438 var_SetBool( p_input, "program-scrambled", false );
440 /* State */
441 var_Create( p_input, "state", VLC_VAR_INTEGER );
442 val.i_int = input_priv(p_input)->i_state;
443 var_Change( p_input, "state", VLC_VAR_SETVALUE, val );
445 /* Rate */
446 var_Create( p_input, "rate", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT );
448 var_Create( p_input, "frame-next", VLC_VAR_VOID );
450 /* Position */
451 var_Create( p_input, "position", VLC_VAR_FLOAT );
453 /* Time */
454 var_Create( p_input, "time", VLC_VAR_INTEGER );
455 var_Create( p_input, "time-offset", VLC_VAR_INTEGER ); /* relative */
457 /* Bookmark */
458 var_Create( p_input, "bookmark", VLC_VAR_INTEGER | VLC_VAR_ISCOMMAND );
459 var_Change( p_input, "bookmark", VLC_VAR_SETTEXT, _("Bookmark") );
461 /* Program */
462 var_Create( p_input, "program", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
463 var_Get( p_input, "program", &val );
464 if( val.i_int <= 0 )
465 var_Change( p_input, "program", VLC_VAR_DELCHOICE, val );
466 var_Change( p_input, "program", VLC_VAR_SETTEXT, _("Program") );
468 /* Programs */
469 var_Create( p_input, "programs", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
470 var_Change( p_input, "programs", VLC_VAR_SETTEXT, _("Programs") );
472 /* Title */
473 var_Create( p_input, "title", VLC_VAR_INTEGER );
474 var_Change( p_input, "title", VLC_VAR_SETTEXT, _("Title") );
476 /* Chapter */
477 var_Create( p_input, "chapter", VLC_VAR_INTEGER );
478 var_Change( p_input, "chapter", VLC_VAR_SETTEXT, _("Chapter") );
480 /* Delay */
481 var_Create( p_input, "audio-delay", VLC_VAR_INTEGER );
482 var_SetInteger( p_input, "audio-delay",
483 VLC_TICK_FROM_MS( var_GetInteger( p_input, "audio-desync" ) ) );
484 var_Create( p_input, "spu-delay", VLC_VAR_INTEGER );
486 val.i_int = -1;
487 /* Video ES */
488 var_Create( p_input, "video-es", VLC_VAR_INTEGER );
489 var_Change( p_input, "video-es", VLC_VAR_SETVALUE, val );
490 var_Change( p_input, "video-es", VLC_VAR_SETTEXT, _("Video Track") );
492 /* Audio ES */
493 var_Create( p_input, "audio-es", VLC_VAR_INTEGER );
494 var_Change( p_input, "audio-es", VLC_VAR_SETVALUE, val );
495 var_Change( p_input, "audio-es", VLC_VAR_SETTEXT, _("Audio Track") );
497 /* Spu ES */
498 var_Create( p_input, "spu-es", VLC_VAR_INTEGER );
499 var_Change( p_input, "spu-es", VLC_VAR_SETVALUE, val );
500 var_Change( p_input, "spu-es", VLC_VAR_SETTEXT, _("Subtitle Track") );
502 var_Create( p_input, "spu-choice", VLC_VAR_INTEGER );
503 var_SetInteger( p_input, "spu-choice", -1 );
505 /* Special read only objects variables for intf */
506 var_Create( p_input, "bookmarks", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
508 var_Create( p_input, "length", VLC_VAR_INTEGER );
510 var_Create( p_input, "bit-rate", VLC_VAR_INTEGER );
511 var_Create( p_input, "sample-rate", VLC_VAR_INTEGER );
513 /* Special "intf-event" variable. */
514 var_Create( p_input, "intf-event", VLC_VAR_INTEGER );
516 /* Add all callbacks
517 * XXX we put callback only in non preparsing mode. We need to create the variable
518 * unless someone want to check all var_Get/var_Change return value ... */
519 if( !input_priv(p_input)->b_preparsing )
520 InputAddCallbacks( p_input, p_input_callbacks );
523 /*****************************************************************************
524 * input_LegacyVarNavigation:
525 * Create all remaining control object variables
526 *****************************************************************************/
527 static void input_LegacyVarNavigation( input_thread_t *p_input )
529 /* Create more command variables */
530 if( input_priv(p_input)->i_title > 1 )
532 if( var_Type( p_input, "next-title" ) == 0 ) {
533 var_Create( p_input, "next-title", VLC_VAR_VOID );
534 var_Change( p_input, "next-title", VLC_VAR_SETTEXT,
535 _("Next title") );
536 var_AddCallback( p_input, "next-title", TitleCallback, NULL );
539 if( var_Type( p_input, "prev-title" ) == 0 ) {
540 var_Create( p_input, "prev-title", VLC_VAR_VOID );
541 var_Change( p_input, "prev-title", VLC_VAR_SETTEXT,
542 _("Previous title") );
543 var_AddCallback( p_input, "prev-title", TitleCallback, NULL );
546 if( var_Type( p_input, "menu-title" ) == 0 ) {
547 var_Create( p_input, "menu-title", VLC_VAR_VOID );
548 var_Change( p_input, "menu-title", VLC_VAR_SETTEXT,
549 _("Menu title") );
550 var_AddCallback( p_input, "menu-title", TitleCallback, NULL );
553 if( var_Type( p_input, "menu-popup" ) == 0 ) {
554 var_Create( p_input, "menu-popup", VLC_VAR_VOID );
555 var_Change( p_input, "menu-popup", VLC_VAR_SETTEXT,
556 _("Menu popup") );
557 var_AddCallback( p_input, "menu-popup", TitleCallback, NULL );
561 /* Create titles and chapters */
562 var_Change( p_input, "title", VLC_VAR_CLEARCHOICES );
564 for( int i = 0; i < input_priv(p_input)->i_title; i++ )
566 vlc_value_t val2, text2;
567 char title[sizeof("title ") + 3 * sizeof (int)];
569 /* Add Navigation entries */
570 sprintf( title, "title %2u", i );
571 var_Destroy( p_input, title );
572 var_Create( p_input, title, VLC_VAR_INTEGER | VLC_VAR_ISCOMMAND );
573 var_AddCallback( p_input, title,
574 NavigationCallback, (void *)(intptr_t)i );
576 char psz_length[MSTRTIME_MAX_SIZE + sizeof(" []")];
577 if( input_priv(p_input)->title[i]->i_length > 0 )
579 strcpy( psz_length, " [" );
580 secstotimestr( &psz_length[2], SEC_FROM_VLC_TICK(input_priv(p_input)->title[i]->i_length) );
581 strcat( psz_length, "]" );
583 else
584 psz_length[0] = '\0';
586 char *titlestr;
587 if( input_priv(p_input)->title[i]->psz_name == NULL ||
588 *input_priv(p_input)->title[i]->psz_name == '\0' )
590 if( asprintf( &titlestr, _("Title %i%s"),
591 i + input_priv(p_input)->i_title_offset, psz_length ) == -1 )
592 continue;
594 else
596 if( asprintf( &titlestr, "%s%s",
597 input_priv(p_input)->title[i]->psz_name, psz_length ) == -1 )
598 continue;
601 /* Add title choice */
602 val2.i_int = i;
603 var_Change( p_input, "title", VLC_VAR_ADDCHOICE, val2,
604 (const char *)titlestr );
606 free( titlestr );
608 for( int j = 0; j < input_priv(p_input)->title[i]->i_seekpoint; j++ )
610 val2.i_int = j;
612 if( input_priv(p_input)->title[i]->seekpoint[j]->psz_name == NULL ||
613 *input_priv(p_input)->title[i]->seekpoint[j]->psz_name == '\0' )
615 /* Default value */
616 if( asprintf( &text2.psz_string, _("Chapter %i"),
617 j + input_priv(p_input)->i_seekpoint_offset ) == -1 )
618 continue;
620 else
622 text2.psz_string =
623 strdup( input_priv(p_input)->title[i]->seekpoint[j]->psz_name );
626 var_Change( p_input, title, VLC_VAR_ADDCHOICE, val2,
627 (const char *)text2.psz_string );
628 free( text2.psz_string );
634 /*****************************************************************************
635 * input_LegacyVarTitle:
636 * Create all variables for a title
637 *****************************************************************************/
638 static void input_LegacyVarTitle( input_thread_t *p_input, int i_title )
640 const input_title_t *t = input_priv(p_input)->title[i_title];
641 vlc_value_t text;
642 int i;
644 /* Create/Destroy command variables */
645 if( t->i_seekpoint <= 1 )
647 var_Destroy( p_input, "next-chapter" );
648 var_Destroy( p_input, "prev-chapter" );
650 else if( var_Type( p_input, "next-chapter" ) == 0 )
652 var_Create( p_input, "next-chapter", VLC_VAR_VOID );
653 var_Change( p_input, "next-chapter", VLC_VAR_SETTEXT,
654 _("Next chapter") );
655 var_AddCallback( p_input, "next-chapter", SeekpointCallback, NULL );
657 var_Create( p_input, "prev-chapter", VLC_VAR_VOID );
658 var_Change( p_input, "prev-chapter", VLC_VAR_SETTEXT,
659 _("Previous chapter") );
660 var_AddCallback( p_input, "prev-chapter", SeekpointCallback, NULL );
663 /* Build chapter list */
664 var_Change( p_input, "chapter", VLC_VAR_CLEARCHOICES );
665 for( i = 0; i < t->i_seekpoint; i++ )
667 vlc_value_t val;
668 val.i_int = i;
670 if( t->seekpoint[i]->psz_name == NULL ||
671 *t->seekpoint[i]->psz_name == '\0' )
673 /* Default value */
674 if( asprintf( &text.psz_string, _("Chapter %i"),
675 i + input_priv(p_input)->i_seekpoint_offset ) == -1 )
676 continue;
678 else
680 text.psz_string = strdup( t->seekpoint[i]->psz_name );
683 var_Change( p_input, "chapter", VLC_VAR_ADDCHOICE, val,
684 (const char *)text.psz_string );
685 free( text.psz_string );
689 /*****************************************************************************
690 * input_ConfigVarInit:
691 * Create all config object variables
692 *****************************************************************************/
693 void input_ConfigVarInit ( input_thread_t *p_input )
695 /* Create Object Variables for private use only */
697 if( !input_priv(p_input)->b_preparsing )
699 var_Create( p_input, "video", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
700 var_Create( p_input, "audio", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
701 var_Create( p_input, "spu", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
703 var_Create( p_input, "audio-track", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
704 var_Create( p_input, "sub-track", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
706 var_Create( p_input, "audio-language",
707 VLC_VAR_STRING|VLC_VAR_DOINHERIT );
708 var_Create( p_input, "sub-language",
709 VLC_VAR_STRING|VLC_VAR_DOINHERIT );
710 var_Create( p_input, "menu-language",
711 VLC_VAR_STRING|VLC_VAR_DOINHERIT );
713 var_Create( p_input, "audio-track-id",
714 VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
715 var_Create( p_input, "sub-track-id",
716 VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
718 var_Create( p_input, "sub-file", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
719 var_Create( p_input, "sub-autodetect-file", VLC_VAR_BOOL |
720 VLC_VAR_DOINHERIT );
721 var_Create( p_input, "sub-autodetect-path", VLC_VAR_STRING |
722 VLC_VAR_DOINHERIT );
723 var_Create( p_input, "sub-autodetect-fuzzy", VLC_VAR_INTEGER |
724 VLC_VAR_DOINHERIT );
726 var_Create( p_input, "sout", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
727 var_Create( p_input, "sout-all", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
728 var_Create( p_input, "sout-audio", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
729 var_Create( p_input, "sout-video", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
730 var_Create( p_input, "sout-spu", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
731 var_Create( p_input, "sout-keep", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
733 var_Create( p_input, "input-repeat",
734 VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
735 var_Create( p_input, "start-time", VLC_VAR_FLOAT|VLC_VAR_DOINHERIT );
736 var_Create( p_input, "stop-time", VLC_VAR_FLOAT|VLC_VAR_DOINHERIT );
737 var_Create( p_input, "run-time", VLC_VAR_FLOAT|VLC_VAR_DOINHERIT );
738 var_Create( p_input, "input-fast-seek", VLC_VAR_BOOL|VLC_VAR_DOINHERIT );
740 var_Create( p_input, "input-slave",
741 VLC_VAR_STRING | VLC_VAR_DOINHERIT );
743 var_Create( p_input, "audio-desync",
744 VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
745 var_Create( p_input, "cr-average",
746 VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
747 var_Create( p_input, "clock-synchro",
748 VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
751 /* */
752 var_Create( p_input, "input-record-native", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
754 /* */
755 var_Create( p_input, "access", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
756 var_Create( p_input, "demux", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
757 var_Create( p_input, "demux-filter", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
758 var_Create( p_input, "stream-filter", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
760 /* Meta */
761 var_Create( p_input, "meta-title", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
762 var_Create( p_input, "meta-author", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
763 var_Create( p_input, "meta-artist", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
764 var_Create( p_input, "meta-genre", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
765 var_Create( p_input, "meta-copyright", VLC_VAR_STRING | VLC_VAR_DOINHERIT);
766 var_Create( p_input, "meta-description", VLC_VAR_STRING|VLC_VAR_DOINHERIT);
767 var_Create( p_input, "meta-date", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
768 var_Create( p_input, "meta-url", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
771 /*****************************************************************************
772 * Callbacks managements:
773 *****************************************************************************/
774 static void InputAddCallbacks( input_thread_t *p_input,
775 const vlc_input_callback_t *p_callbacks )
777 int i;
778 for( i = 0; p_callbacks[i].psz_name != NULL; i++ )
779 var_AddCallback( p_input,
780 p_callbacks[i].psz_name,
781 p_callbacks[i].callback, NULL );
784 static void InputDelCallbacks( input_thread_t *p_input,
785 const vlc_input_callback_t *p_callbacks )
787 int i;
788 for( i = 0; p_callbacks[i].psz_name != NULL; i++ )
789 var_DelCallback( p_input,
790 p_callbacks[i].psz_name,
791 p_callbacks[i].callback, NULL );
794 /*****************************************************************************
795 * All Callbacks:
796 *****************************************************************************/
797 static int StateCallback( vlc_object_t *p_this, char const *psz_cmd,
798 vlc_value_t oldval, vlc_value_t newval,
799 void *p_data )
801 input_thread_t *p_input = (input_thread_t*)p_this;
802 VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval); VLC_UNUSED(p_data);
804 if( newval.i_int == PLAYING_S || newval.i_int == PAUSE_S )
806 input_ControlPushHelper( p_input, INPUT_CONTROL_SET_STATE, &newval );
807 return VLC_SUCCESS;
810 return VLC_EGENERIC;
813 static int RateCallback( vlc_object_t *p_this, char const *psz_cmd,
814 vlc_value_t oldval, vlc_value_t newval, void *p_data )
816 input_thread_t *p_input = (input_thread_t*)p_this;
817 VLC_UNUSED(oldval); VLC_UNUSED(p_data); VLC_UNUSED(psz_cmd);
819 newval.i_int = INPUT_RATE_DEFAULT / newval.f_float;
820 input_ControlPushHelper( p_input, INPUT_CONTROL_SET_RATE, &newval );
822 return VLC_SUCCESS;
825 static int PositionCallback( vlc_object_t *p_this, char const *psz_cmd,
826 vlc_value_t oldval, vlc_value_t newval,
827 void *p_data )
829 input_thread_t *p_input = (input_thread_t*)p_this;
831 VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval); VLC_UNUSED(p_data);
833 /* Update "length" for better intf behaviour */
834 const vlc_tick_t i_length = var_GetInteger( p_input, "length" );
835 if( i_length > 0 && newval.f_float >= 0.f && newval.f_float <= 1.f )
837 vlc_value_t val;
839 val.i_int = i_length * newval.f_float;
840 var_Change( p_input, "time", VLC_VAR_SETVALUE, val );
843 input_SetPosition( p_input, newval.f_float,
844 var_GetBool( p_input, "input-fast-seek" ) );
845 return VLC_SUCCESS;
848 static int TimeCallback( vlc_object_t *p_this, char const *psz_cmd,
849 vlc_value_t oldval, vlc_value_t newval, void *p_data )
851 input_thread_t *p_input = (input_thread_t*)p_this;
852 VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval); VLC_UNUSED(p_data);
854 /* Update "position" for better intf behaviour */
855 const int64_t i_length = var_GetInteger( p_input, "length" );
856 if( i_length > 0 && newval.i_int >= 0 && newval.i_int <= i_length )
858 vlc_value_t val;
860 val.f_float = (double)newval.i_int/(double)i_length;
861 var_Change( p_input, "position", VLC_VAR_SETVALUE, val );
863 * Notify the intf that a new event has been occurred.
864 * XXX this is a bit hackish but it's the only way to do it now.
866 var_SetInteger( p_input, "intf-event", INPUT_EVENT_POSITION );
869 input_SetTime( p_input, newval.i_int,
870 var_GetBool( p_input, "input-fast-seek" ) );
871 return VLC_SUCCESS;
874 static int TimeOffsetCallback( vlc_object_t *obj, char const *varname,
875 vlc_value_t prev, vlc_value_t cur, void *data )
877 VLC_UNUSED(varname); VLC_UNUSED(prev); VLC_UNUSED(data);
879 int64_t i_time = var_GetInteger( obj, "time" ) + cur.i_int;
880 if( i_time < 0 )
881 i_time = 0;
882 var_SetInteger( obj, "time", i_time );
883 return VLC_SUCCESS;
886 static int ProgramCallback( vlc_object_t *p_this, char const *psz_cmd,
887 vlc_value_t oldval, vlc_value_t newval,
888 void *p_data )
890 input_thread_t *p_input = (input_thread_t*)p_this;
891 VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval); VLC_UNUSED(p_data);
893 input_ControlPushHelper( p_input, INPUT_CONTROL_SET_PROGRAM, &newval );
895 return VLC_SUCCESS;
898 static int TitleCallback( vlc_object_t *p_this, char const *psz_cmd,
899 vlc_value_t oldval, vlc_value_t newval,
900 void *p_data )
902 input_thread_t *p_input = (input_thread_t*)p_this;
903 vlc_value_t val;
904 size_t count;
905 VLC_UNUSED(oldval); VLC_UNUSED(p_data);
907 if( !strcmp( psz_cmd, "next-title" ) )
909 input_ControlPushHelper( p_input, INPUT_CONTROL_SET_TITLE_NEXT, NULL );
911 val.i_int = var_GetInteger( p_input, "title" ) + 1;
912 var_Change( p_input, "title", VLC_VAR_CHOICESCOUNT, &count );
913 if( (size_t)val.i_int < count )
914 var_Change( p_input, "title", VLC_VAR_SETVALUE, val );
916 else if( !strcmp( psz_cmd, "prev-title" ) )
918 input_ControlPushHelper( p_input, INPUT_CONTROL_SET_TITLE_PREV, NULL );
920 val.i_int = var_GetInteger( p_input, "title" ) - 1;
921 if( val.i_int >= 0 )
922 var_Change( p_input, "title", VLC_VAR_SETVALUE, val );
924 else if( !strcmp( psz_cmd, "menu-title" ) )
926 input_ControlPushHelper( p_input, INPUT_CONTROL_NAV_MENU, NULL );
928 else if( !strcmp( psz_cmd, "menu-popup" ) )
930 input_ControlPushHelper( p_input, INPUT_CONTROL_NAV_POPUP, NULL );
932 else
934 input_ControlPushHelper( p_input, INPUT_CONTROL_SET_TITLE, &newval );
937 return VLC_SUCCESS;
940 static int SeekpointCallback( vlc_object_t *p_this, char const *psz_cmd,
941 vlc_value_t oldval, vlc_value_t newval,
942 void *p_data )
944 input_thread_t *p_input = (input_thread_t*)p_this;
945 vlc_value_t val;
946 size_t count;
947 VLC_UNUSED(oldval); VLC_UNUSED(p_data);
949 if( !strcmp( psz_cmd, "next-chapter" ) )
951 input_ControlPushHelper( p_input, INPUT_CONTROL_SET_SEEKPOINT_NEXT, NULL );
953 val.i_int = var_GetInteger( p_input, "chapter" ) + 1;
954 var_Change( p_input, "chapter", VLC_VAR_CHOICESCOUNT, &count );
955 if( (size_t)val.i_int < count )
956 var_Change( p_input, "chapter", VLC_VAR_SETVALUE, val );
958 else if( !strcmp( psz_cmd, "prev-chapter" ) )
960 input_ControlPushHelper( p_input, INPUT_CONTROL_SET_SEEKPOINT_PREV, NULL );
962 val.i_int = var_GetInteger( p_input, "chapter" ) - 1;
963 if( val.i_int >= 0 )
964 var_Change( p_input, "chapter", VLC_VAR_SETVALUE, val );
966 else
968 input_ControlPushHelper( p_input, INPUT_CONTROL_SET_SEEKPOINT, &newval );
971 return VLC_SUCCESS;
974 static int NavigationCallback( vlc_object_t *p_this, char const *psz_cmd,
975 vlc_value_t oldval, vlc_value_t newval,
976 void *p_data )
978 input_thread_t *p_input = (input_thread_t*)p_this;
979 vlc_value_t val;
980 VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval);
982 /* Issue a title change */
983 val.i_int = (intptr_t)p_data;
984 input_ControlPushHelper( p_input, INPUT_CONTROL_SET_TITLE, &val );
986 var_Change( p_input, "title", VLC_VAR_SETVALUE, val );
988 /* And a chapter change */
989 input_ControlPushHelper( p_input, INPUT_CONTROL_SET_SEEKPOINT, &newval );
991 var_Change( p_input, "chapter", VLC_VAR_SETVALUE, newval );
993 return VLC_SUCCESS;
996 static int EsVideoCallback( vlc_object_t *p_this, char const *psz_cmd,
997 vlc_value_t oldval, vlc_value_t newval, void *p_data )
999 input_thread_t *p_input = (input_thread_t*)p_this;
1000 VLC_UNUSED( psz_cmd); VLC_UNUSED( oldval ); VLC_UNUSED( p_data );
1002 if( newval.i_int < 0 )
1003 newval.i_int = -VIDEO_ES; /* disable video es */
1004 else
1005 var_SetBool( p_input, "video", true );
1007 input_ControlPushHelper( p_input, INPUT_CONTROL_SET_ES, &newval );
1009 return VLC_SUCCESS;
1012 static int EsAudioCallback( vlc_object_t *p_this, char const *psz_cmd,
1013 vlc_value_t oldval, vlc_value_t newval, void *p_data )
1015 input_thread_t *p_input = (input_thread_t*)p_this;
1016 VLC_UNUSED( psz_cmd); VLC_UNUSED( oldval ); VLC_UNUSED( p_data );
1018 if( newval.i_int < 0 )
1019 newval.i_int = -AUDIO_ES; /* disable audio es */
1020 else
1021 var_SetBool( p_input, "audio", true );
1023 input_ControlPushHelper( p_input, INPUT_CONTROL_SET_ES, &newval );
1025 return VLC_SUCCESS;
1028 static int EsSpuCallback( vlc_object_t *p_this, char const *psz_cmd,
1029 vlc_value_t oldval, vlc_value_t newval, void *p_data )
1031 input_thread_t *p_input = (input_thread_t*)p_this;
1032 VLC_UNUSED( psz_cmd); VLC_UNUSED( oldval ); VLC_UNUSED( p_data );
1034 if( newval.i_int < 0 )
1035 newval.i_int = -SPU_ES; /* disable spu es */
1036 else
1037 var_SetBool( p_input, "spu", true );
1039 input_ControlPushHelper( p_input, INPUT_CONTROL_SET_ES, &newval );
1041 return VLC_SUCCESS;
1044 static int EsDelayCallback ( vlc_object_t *p_this, char const *psz_cmd,
1045 vlc_value_t oldval, vlc_value_t newval, void *p_data )
1047 input_thread_t *p_input = (input_thread_t*)p_this;
1048 VLC_UNUSED(oldval); VLC_UNUSED(p_data);
1050 if( !strcmp( psz_cmd, "audio-delay" ) )
1052 input_ControlPushHelper( p_input, INPUT_CONTROL_SET_AUDIO_DELAY, &newval );
1054 else if( !strcmp( psz_cmd, "spu-delay" ) )
1056 input_ControlPushHelper( p_input, INPUT_CONTROL_SET_SPU_DELAY, &newval );
1058 return VLC_SUCCESS;
1061 static int BookmarkCallback( vlc_object_t *p_this, char const *psz_cmd,
1062 vlc_value_t oldval, vlc_value_t newval,
1063 void *p_data )
1065 input_thread_t *p_input = (input_thread_t*)p_this;
1066 VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval); VLC_UNUSED(p_data);
1068 input_ControlPushHelper( p_input, INPUT_CONTROL_SET_BOOKMARK, &newval );
1070 return VLC_SUCCESS;
1073 static int RecordCallback( vlc_object_t *p_this, char const *psz_cmd,
1074 vlc_value_t oldval, vlc_value_t newval,
1075 void *p_data )
1077 input_thread_t *p_input = (input_thread_t*)p_this;
1078 VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval); VLC_UNUSED(p_data);
1080 input_ControlPushHelper( p_input, INPUT_CONTROL_SET_RECORD_STATE, &newval );
1082 return VLC_SUCCESS;
1085 static int FrameNextCallback( vlc_object_t *p_this, char const *psz_cmd,
1086 vlc_value_t oldval, vlc_value_t newval,
1087 void *p_data )
1089 input_thread_t *p_input = (input_thread_t*)p_this;
1090 VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval); VLC_UNUSED(p_data);
1091 VLC_UNUSED(newval);
1093 input_ControlPushHelper( p_input, INPUT_CONTROL_SET_FRAME_NEXT, NULL );
1095 return VLC_SUCCESS;