1 /*****************************************************************************
2 * var.c: object variables for input thread
3 *****************************************************************************
4 * Copyright (C) 2004-2007 VLC authors and VideoLAN
6 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation; either version 2.1 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
23 /*****************************************************************************
25 *****************************************************************************/
30 #include <vlc_common.h>
31 #include <vlc_memstream.h>
37 #include "input_internal.h"
39 /*****************************************************************************
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 TimeOffsetCallback( vlc_object_t
*p_this
, char const *psz_cmd
,
51 vlc_value_t oldval
, vlc_value_t newval
, void * );
52 static int ProgramCallback ( vlc_object_t
*p_this
, char const *psz_cmd
,
53 vlc_value_t oldval
, vlc_value_t newval
, void * );
54 static int TitleCallback ( vlc_object_t
*p_this
, char const *psz_cmd
,
55 vlc_value_t oldval
, vlc_value_t newval
, void * );
56 static int SeekpointCallback( vlc_object_t
*p_this
, char const *psz_cmd
,
57 vlc_value_t oldval
, vlc_value_t newval
, void * );
58 static int NavigationCallback( vlc_object_t
*p_this
, char const *psz_cmd
,
59 vlc_value_t oldval
, vlc_value_t newval
, void * );
60 static int EsVideoCallback ( vlc_object_t
*p_this
, char const *psz_cmd
,
61 vlc_value_t oldval
, vlc_value_t newval
, void * );
62 static int EsAudioCallback ( vlc_object_t
*p_this
, char const *psz_cmd
,
63 vlc_value_t oldval
, vlc_value_t newval
, void * );
64 static int EsSpuCallback ( vlc_object_t
*p_this
, char const *psz_cmd
,
65 vlc_value_t oldval
, vlc_value_t newval
, void * );
66 static int EsDelayCallback ( vlc_object_t
*p_this
, char const *psz_cmd
,
67 vlc_value_t oldval
, vlc_value_t newval
, void * );
69 static int BookmarkCallback( vlc_object_t
*p_this
, char const *psz_cmd
,
70 vlc_value_t oldval
, vlc_value_t newval
, void * );
72 static int RecordCallback( vlc_object_t
*p_this
, char const *psz_cmd
,
73 vlc_value_t oldval
, vlc_value_t newval
,
75 static int FrameNextCallback( vlc_object_t
*p_this
, char const *psz_cmd
,
76 vlc_value_t oldval
, vlc_value_t newval
,
78 static int SubFpsCallback( vlc_object_t
*p_this
, char const *psz_cmd
,
79 vlc_value_t oldval
, vlc_value_t newval
,
81 static void input_LegacyVarTitle( input_thread_t
*p_input
, int i_title
);
82 static void input_LegacyVarNavigation( input_thread_t
*p_input
);
87 vlc_callback_t callback
;
88 } vlc_input_callback_t
;
90 static void InputAddCallbacks( input_thread_t
*, const vlc_input_callback_t
* );
92 #ifdef CALLBACK /* For windows */
93 # undef CALLBACK /* We don't care of this one here */
95 /* List all callbacks added by input */
96 #define CALLBACK(name,cb) { name, cb }
97 static const vlc_input_callback_t p_input_callbacks
[] =
99 CALLBACK( "state", StateCallback
),
100 CALLBACK( "rate", RateCallback
),
101 CALLBACK( "position", PositionCallback
),
102 CALLBACK( "time", TimeCallback
),
103 CALLBACK( "time-offset", TimeOffsetCallback
),
104 CALLBACK( "bookmark", BookmarkCallback
),
105 CALLBACK( "program", ProgramCallback
),
106 CALLBACK( "title", TitleCallback
),
107 CALLBACK( "chapter", SeekpointCallback
),
108 CALLBACK( "audio-delay", EsDelayCallback
),
109 CALLBACK( "spu-delay", EsDelayCallback
),
110 CALLBACK( "video-es", EsVideoCallback
),
111 CALLBACK( "audio-es", EsAudioCallback
),
112 CALLBACK( "spu-es", EsSpuCallback
),
113 CALLBACK( "record", RecordCallback
),
114 CALLBACK( "frame-next", FrameNextCallback
),
115 CALLBACK( "sub-fps", SubFpsCallback
),
117 CALLBACK( NULL
, NULL
)
121 static void Trigger( input_thread_t
*p_input
, int i_type
)
123 var_SetInteger( p_input
, "intf-event", i_type
);
125 static void VarListAdd( input_thread_t
*p_input
,
126 const char *psz_variable
,
127 int i_value
, const char *psz_text
)
133 var_Change( p_input
, psz_variable
, VLC_VAR_ADDCHOICE
, val
, psz_text
);
135 static void VarListDel( input_thread_t
*p_input
,
136 const char *psz_variable
,
144 var_Change( p_input
, psz_variable
, VLC_VAR_DELCHOICE
, val
);
148 var_Change( p_input
, psz_variable
, VLC_VAR_CLEARCHOICES
);
151 static void VarListSelect( input_thread_t
*p_input
,
152 const char *psz_variable
,
158 var_Change( p_input
, psz_variable
, VLC_VAR_SETVALUE
, val
);
160 static const char *GetEsVarName( enum es_format_category_e i_cat
)
175 static void UpdateBookmarksOption( input_thread_t
*p_input
)
177 input_thread_private_t
*priv
= input_priv(p_input
);
178 input_item_t
* item
= priv
->p_item
;
179 struct vlc_memstream vstr
;
181 vlc_memstream_open( &vstr
);
182 vlc_memstream_puts( &vstr
, "bookmarks=" );
184 vlc_mutex_lock( &item
->lock
);
185 var_Change( p_input
, "bookmark", VLC_VAR_CLEARCHOICES
);
187 for( int i
= 0; i
< priv
->i_bookmark
; i
++ )
189 seekpoint_t
const* sp
= priv
->pp_bookmark
[i
];
191 /* Add bookmark to choice-list */
192 var_Change( p_input
, "bookmark", VLC_VAR_ADDCHOICE
,
193 (vlc_value_t
){ .i_int
= i
}, sp
->psz_name
);
195 /* Append bookmark to option-buffer */
196 /* TODO: escape inappropriate values */
197 vlc_memstream_printf( &vstr
, "%s{name=%s,time=%.3f}",
198 i
> 0 ? "," : "", sp
->psz_name
, secf_from_vlc_tick(sp
->i_time_offset
) );
201 if( vlc_memstream_close( &vstr
) )
203 vlc_mutex_unlock( &item
->lock
);
207 /* XXX: The below is ugly and should be fixed elsewhere, but in order to
208 * not have more than one "bookmarks=" option associated with the item, we
209 * need to remove any existing ones before adding the new one. This logic
210 * should exist in input_item_AddOption with "OPTION_UNIQUE & <an overwrite
211 * flag>, but until then we handle it here. */
213 char** const orig_beg
= &item
->ppsz_options
[0];
214 char** const orig_end
= orig_beg
+ item
->i_options
;
215 char** end
= orig_end
;
217 for( char** option
= orig_beg
; option
!= end
; )
219 if( strncmp( *option
, "bookmarks=", 10 ) )
224 /* It might be tempting to optimize the below by overwriting
225 * *option with the value of the last element, however; we want to
226 * preserve the order of the other options (as behavior might
228 memmove( option
, option
+ 1, ( --end
- option
) * sizeof *end
);
232 if( end
!= orig_end
) /* we removed at least 1 option */
235 item
->i_options
= end
- orig_beg
+ 1;
236 vlc_mutex_unlock( &item
->lock
);
238 else /* nothing removed, add the usual way */
240 vlc_mutex_unlock( &item
->lock
);
241 input_item_AddOption( item
, vstr
.ptr
, VLC_INPUT_OPTION_UNIQUE
);
246 static inline bool EsFmtIsTeletext( const es_format_t
*p_fmt
)
248 return p_fmt
->i_cat
== SPU_ES
&& p_fmt
->i_codec
== VLC_CODEC_TELETEXT
;
251 void input_LegacyEvents( input_thread_t
*p_input
,
252 const struct vlc_input_event
*event
, void *user_data
)
257 switch( event
->type
)
259 case INPUT_EVENT_STATE
:
260 val
.i_int
= event
->state
;
261 var_Change( p_input
, "state", VLC_VAR_SETVALUE
, val
);
263 case INPUT_EVENT_DEAD
:
265 case INPUT_EVENT_RATE
:
266 val
.f_float
= event
->rate
;
267 var_Change( p_input
, "rate", VLC_VAR_SETVALUE
, val
);
269 case INPUT_EVENT_CAPABILITIES
:
270 var_SetBool( p_input
, "can-seek",
271 event
->capabilities
& VLC_INPUT_CAPABILITIES_SEEKABLE
);
272 var_SetBool( p_input
, "can-pause",
273 event
->capabilities
& VLC_INPUT_CAPABILITIES_PAUSEABLE
);
274 var_SetBool( p_input
, "can-rate",
275 event
->capabilities
& VLC_INPUT_CAPABILITIES_CHANGE_RATE
);
276 var_SetBool( p_input
, "can-rewind",
277 event
->capabilities
& VLC_INPUT_CAPABILITIES_REWINDABLE
);
278 var_SetBool( p_input
, "can-record",
279 event
->capabilities
& VLC_INPUT_CAPABILITIES_RECORDABLE
);
281 case INPUT_EVENT_POSITION
:
282 val
.f_float
= event
->position
.percentage
;
283 var_Change( p_input
, "position", VLC_VAR_SETVALUE
, val
);
284 val
.i_int
= event
->position
.ms
;
285 var_Change( p_input
, "time", VLC_VAR_SETVALUE
, val
);
287 case INPUT_EVENT_LENGTH
:
288 /* FIXME ugly + what about meta change event ? */
289 if( var_GetInteger( p_input
, "length" ) == event
->length
)
291 val
.i_int
= event
->length
;
292 var_Change( p_input
, "length", VLC_VAR_SETVALUE
, val
);
294 case INPUT_EVENT_TITLE
:
295 val
.i_int
= event
->title
.action
== VLC_INPUT_TITLE_NEW_LIST
? 0 : event
->title
.selected_idx
;
296 var_Change( p_input
, "title", VLC_VAR_SETVALUE
, val
);
297 input_LegacyVarNavigation( p_input
);
298 input_LegacyVarTitle( p_input
, val
.i_int
);
300 case INPUT_EVENT_CHAPTER
:
302 val
.i_int
= event
->chapter
.seekpoint
;
303 var_Change( p_input
, "chapter", VLC_VAR_SETVALUE
, val
);
306 char psz_title
[sizeof ("title ") + 3 * sizeof (int)];
307 sprintf( psz_title
, "title %2u", event
->chapter
.title
);
308 var_Change( p_input
, psz_title
, VLC_VAR_SETVALUE
, val
);
310 case INPUT_EVENT_PROGRAM
:
311 switch (event
->program
.action
)
313 case VLC_INPUT_PROGRAM_ADDED
:
314 VarListAdd( p_input
, "program", event
->program
.id
,
315 event
->program
.title
);
317 case VLC_INPUT_PROGRAM_DELETED
:
318 VarListDel( p_input
, "program", event
->program
.id
);
320 case VLC_INPUT_PROGRAM_UPDATED
:
321 VarListDel( p_input
, "program", event
->program
.id
);
322 VarListAdd( p_input
, "program", event
->program
.id
,
323 event
->program
.title
);
325 case VLC_INPUT_PROGRAM_SELECTED
:
326 VarListSelect( p_input
, "program", event
->program
.id
);
328 case VLC_INPUT_PROGRAM_SCRAMBLED
:
329 if( var_GetInteger( p_input
, "program" ) != event
->program
.id
)
331 var_SetBool( p_input
, "program-scrambled", event
->program
.scrambled
);
336 switch (event
->es
.action
)
338 case VLC_INPUT_ES_ADDED
:
340 const char *varname
= GetEsVarName( event
->es
.fmt
->i_cat
);
344 var_Change( p_input
, varname
, VLC_VAR_CHOICESCOUNT
, &count
);
347 /* First one, we need to add the "Disable" choice */
348 VarListAdd( p_input
, varname
, -1, _("Disable") );
350 VarListAdd( p_input
, varname
, event
->es
.fmt
->i_id
, event
->es
.title
);
353 if( EsFmtIsTeletext( event
->es
.fmt
) )
356 snprintf( psz_page
, sizeof(psz_page
), "%d%2.2x",
357 event
->es
.fmt
->subs
.teletext
.i_magazine
,
358 event
->es
.fmt
->subs
.teletext
.i_page
);
359 VarListAdd( p_input
, "teletext-es", event
->es
.fmt
->i_id
,
360 event
->es
.fmt
->subs
.teletext
.i_magazine
>= 0 ? psz_page
: "" );
364 case VLC_INPUT_ES_DELETED
:
366 const char *varname
= GetEsVarName( event
->es
.fmt
->i_cat
);
368 VarListDel( p_input
, varname
, event
->es
.fmt
->i_id
);
370 if( EsFmtIsTeletext( event
->es
.fmt
) )
371 VarListDel( p_input
, "teletext-es", event
->es
.fmt
->i_id
);
374 case VLC_INPUT_ES_SELECTED
:
375 case VLC_INPUT_ES_UNSELECTED
:
377 int i_id
= event
->es
.action
== VLC_INPUT_ES_SELECTED
378 ? event
->es
.fmt
->i_id
: -1;
379 const char *varname
= GetEsVarName( event
->es
.fmt
->i_cat
);
381 VarListSelect( p_input
, varname
, i_id
);
382 if( EsFmtIsTeletext( event
->es
.fmt
) )
383 VarListSelect( p_input
, "teletext-es", i_id
);
386 case VLC_INPUT_ES_UPDATED
:
390 case INPUT_EVENT_RECORD
:
391 val
.b_bool
= event
->record
;
392 var_Change( p_input
, "record", VLC_VAR_SETVALUE
, val
);
394 case INPUT_EVENT_ITEM_META
:
396 case INPUT_EVENT_ITEM_INFO
:
398 case INPUT_EVENT_ITEM_EPG
:
400 case INPUT_EVENT_STATISTICS
:
402 case INPUT_EVENT_SIGNAL
:
403 val
.f_float
= event
->signal
.quality
;
404 var_Change( p_input
, "signal-quality", VLC_VAR_SETVALUE
, val
);
405 val
.f_float
= event
->signal
.strength
;
406 var_Change( p_input
, "signal-strength", VLC_VAR_SETVALUE
, val
);
408 case INPUT_EVENT_AUDIO_DELAY
:
409 val
.i_int
= event
->audio_delay
;
410 var_Change( p_input
, "audio-delay", VLC_VAR_SETVALUE
, val
);
412 case INPUT_EVENT_SUBTITLE_DELAY
:
413 val
.i_int
= event
->subtitle_delay
;
414 var_Change( p_input
, "spu-delay", VLC_VAR_SETVALUE
, val
);
416 case INPUT_EVENT_BOOKMARK
:
417 UpdateBookmarksOption( p_input
);
419 case INPUT_EVENT_CACHE
:
420 val
.f_float
= event
->cache
;
421 var_Change( p_input
, "cache", VLC_VAR_SETVALUE
, val
);
423 case INPUT_EVENT_VOUT
:
424 case INPUT_EVENT_SUBITEMS
:
425 case INPUT_EVENT_THUMBNAIL_READY
:
426 case INPUT_EVENT_VBI_PAGE
:
427 case INPUT_EVENT_VBI_TRANSPARENCY
:
428 case INPUT_EVENT_SUBS_FPS
:
431 Trigger( p_input
, event
->type
);
434 /*****************************************************************************
435 * input_LegacyVarInit:
436 * Create all control object variables with their callbacks
437 *****************************************************************************/
438 void input_LegacyVarInit ( input_thread_t
*p_input
)
442 var_Create( p_input
, "can-seek", VLC_VAR_BOOL
);
443 var_SetBool( p_input
, "can-seek", true ); /* Fixed later*/
445 var_Create( p_input
, "can-pause", VLC_VAR_BOOL
);
446 var_SetBool( p_input
, "can-pause", true ); /* Fixed later*/
448 var_Create( p_input
, "can-rate", VLC_VAR_BOOL
);
449 var_SetBool( p_input
, "can-rate", false );
451 var_Create( p_input
, "can-rewind", VLC_VAR_BOOL
);
452 var_SetBool( p_input
, "can-rewind", false );
454 var_Create( p_input
, "can-record", VLC_VAR_BOOL
);
455 var_SetBool( p_input
, "can-record", false ); /* Fixed later*/
457 var_Create( p_input
, "record", VLC_VAR_BOOL
);
458 var_SetBool( p_input
, "record", false );
460 var_Create( p_input
, "teletext-es", VLC_VAR_INTEGER
);
461 var_SetInteger( p_input
, "teletext-es", -1 );
463 var_Create( p_input
, "cache", VLC_VAR_FLOAT
);
464 var_SetFloat( p_input
, "cache", 0.0 );
466 var_Create( p_input
, "signal-quality", VLC_VAR_FLOAT
);
467 var_SetFloat( p_input
, "signal-quality", -1 );
469 var_Create( p_input
, "signal-strength", VLC_VAR_FLOAT
);
470 var_SetFloat( p_input
, "signal-strength", -1 );
472 var_Create( p_input
, "program-scrambled", VLC_VAR_BOOL
);
473 var_SetBool( p_input
, "program-scrambled", false );
476 var_Create( p_input
, "state", VLC_VAR_INTEGER
);
477 val
.i_int
= input_priv(p_input
)->i_state
;
478 var_Change( p_input
, "state", VLC_VAR_SETVALUE
, val
);
480 var_Create( p_input
, "frame-next", VLC_VAR_VOID
);
483 var_Create( p_input
, "position", VLC_VAR_FLOAT
);
486 var_Create( p_input
, "time", VLC_VAR_INTEGER
);
487 var_Create( p_input
, "time-offset", VLC_VAR_INTEGER
); /* relative */
490 var_Create( p_input
, "bookmark", VLC_VAR_INTEGER
| VLC_VAR_ISCOMMAND
);
491 var_Change( p_input
, "bookmark", VLC_VAR_SETTEXT
, _("Bookmark") );
494 var_Get( p_input
, "program", &val
);
496 var_Change( p_input
, "program", VLC_VAR_DELCHOICE
, val
);
497 var_Change( p_input
, "program", VLC_VAR_SETTEXT
, _("Program") );
500 var_Change( p_input
, "programs", VLC_VAR_SETTEXT
, _("Programs") );
503 var_Create( p_input
, "title", VLC_VAR_INTEGER
);
504 var_Change( p_input
, "title", VLC_VAR_SETTEXT
, _("Title") );
507 var_Create( p_input
, "chapter", VLC_VAR_INTEGER
);
508 var_Change( p_input
, "chapter", VLC_VAR_SETTEXT
, _("Chapter") );
511 var_Create( p_input
, "audio-delay", VLC_VAR_INTEGER
);
512 var_SetInteger( p_input
, "audio-delay",
513 VLC_TICK_FROM_MS( var_GetInteger( p_input
, "audio-desync" ) ) );
514 var_Create( p_input
, "spu-delay", VLC_VAR_INTEGER
);
518 var_Create( p_input
, "video-es", VLC_VAR_INTEGER
);
519 var_Change( p_input
, "video-es", VLC_VAR_SETVALUE
, val
);
520 var_Change( p_input
, "video-es", VLC_VAR_SETTEXT
, _("Video Track") );
523 var_Create( p_input
, "audio-es", VLC_VAR_INTEGER
);
524 var_Change( p_input
, "audio-es", VLC_VAR_SETVALUE
, val
);
525 var_Change( p_input
, "audio-es", VLC_VAR_SETTEXT
, _("Audio Track") );
528 var_Create( p_input
, "spu-es", VLC_VAR_INTEGER
);
529 var_Change( p_input
, "spu-es", VLC_VAR_SETVALUE
, val
);
530 var_Change( p_input
, "spu-es", VLC_VAR_SETTEXT
, _("Subtitle Track") );
532 var_Create( p_input
, "spu-choice", VLC_VAR_INTEGER
);
533 var_SetInteger( p_input
, "spu-choice", -1 );
535 var_Create( p_input
, "length", VLC_VAR_INTEGER
);
537 var_Create( p_input
, "bit-rate", VLC_VAR_INTEGER
);
538 var_Create( p_input
, "sample-rate", VLC_VAR_INTEGER
);
540 /* Special "intf-event" variable. */
541 var_Create( p_input
, "intf-event", VLC_VAR_INTEGER
);
542 var_Create( p_input
, "sub-fps", VLC_VAR_FLOAT
| VLC_VAR_DOINHERIT
);
545 * XXX we put callback only in non preparsing mode. We need to create the variable
546 * unless someone want to check all var_Get/var_Change return value ... */
547 if( !input_priv(p_input
)->b_preparsing
)
548 InputAddCallbacks( p_input
, p_input_callbacks
);
551 /*****************************************************************************
552 * input_LegacyVarNavigation:
553 * Create all remaining control object variables
554 *****************************************************************************/
555 static void input_LegacyVarNavigation( input_thread_t
*p_input
)
557 /* Create more command variables */
558 if( input_priv(p_input
)->i_title
> 1 )
560 if( var_Type( p_input
, "next-title" ) == 0 ) {
561 var_Create( p_input
, "next-title", VLC_VAR_VOID
);
562 var_Change( p_input
, "next-title", VLC_VAR_SETTEXT
,
564 var_AddCallback( p_input
, "next-title", TitleCallback
, NULL
);
567 if( var_Type( p_input
, "prev-title" ) == 0 ) {
568 var_Create( p_input
, "prev-title", VLC_VAR_VOID
);
569 var_Change( p_input
, "prev-title", VLC_VAR_SETTEXT
,
570 _("Previous title") );
571 var_AddCallback( p_input
, "prev-title", TitleCallback
, NULL
);
574 if( var_Type( p_input
, "menu-title" ) == 0 ) {
575 var_Create( p_input
, "menu-title", VLC_VAR_VOID
);
576 var_Change( p_input
, "menu-title", VLC_VAR_SETTEXT
,
578 var_AddCallback( p_input
, "menu-title", TitleCallback
, NULL
);
581 if( var_Type( p_input
, "menu-popup" ) == 0 ) {
582 var_Create( p_input
, "menu-popup", VLC_VAR_VOID
);
583 var_Change( p_input
, "menu-popup", VLC_VAR_SETTEXT
,
585 var_AddCallback( p_input
, "menu-popup", TitleCallback
, NULL
);
589 /* Create titles and chapters */
590 var_Change( p_input
, "title", VLC_VAR_CLEARCHOICES
);
592 for( int i
= 0; i
< input_priv(p_input
)->i_title
; i
++ )
594 vlc_value_t val2
, text2
;
595 char title
[sizeof("title ") + 3 * sizeof (int)];
597 /* Add Navigation entries */
598 sprintf( title
, "title %2u", i
);
599 var_Destroy( p_input
, title
);
600 var_Create( p_input
, title
, VLC_VAR_INTEGER
| VLC_VAR_ISCOMMAND
);
601 var_AddCallback( p_input
, title
, NavigationCallback
, NULL
);
603 char psz_length
[MSTRTIME_MAX_SIZE
+ sizeof(" []")];
604 if( input_priv(p_input
)->title
[i
]->i_length
> 0 )
606 strcpy( psz_length
, " [" );
607 secstotimestr( &psz_length
[2], SEC_FROM_VLC_TICK(input_priv(p_input
)->title
[i
]->i_length
) );
608 strcat( psz_length
, "]" );
611 psz_length
[0] = '\0';
614 if( input_priv(p_input
)->title
[i
]->psz_name
== NULL
||
615 *input_priv(p_input
)->title
[i
]->psz_name
== '\0' )
617 if( asprintf( &titlestr
, _("Title %i%s"),
618 i
+ input_priv(p_input
)->i_title_offset
, psz_length
) == -1 )
623 if( asprintf( &titlestr
, "%s%s",
624 input_priv(p_input
)->title
[i
]->psz_name
, psz_length
) == -1 )
628 /* Add title choice */
630 var_Change( p_input
, "title", VLC_VAR_ADDCHOICE
, val2
,
631 (const char *)titlestr
);
635 for( int j
= 0; j
< input_priv(p_input
)->title
[i
]->i_seekpoint
; j
++ )
639 if( input_priv(p_input
)->title
[i
]->seekpoint
[j
]->psz_name
== NULL
||
640 *input_priv(p_input
)->title
[i
]->seekpoint
[j
]->psz_name
== '\0' )
643 if( asprintf( &text2
.psz_string
, _("Chapter %i"),
644 j
+ input_priv(p_input
)->i_seekpoint_offset
) == -1 )
650 strdup( input_priv(p_input
)->title
[i
]->seekpoint
[j
]->psz_name
);
653 var_Change( p_input
, title
, VLC_VAR_ADDCHOICE
, val2
,
654 (const char *)text2
.psz_string
);
655 free( text2
.psz_string
);
661 /*****************************************************************************
662 * input_LegacyVarTitle:
663 * Create all variables for a title
664 *****************************************************************************/
665 static void input_LegacyVarTitle( input_thread_t
*p_input
, int i_title
)
667 const input_title_t
*t
= input_priv(p_input
)->title
[i_title
];
671 /* Create/Destroy command variables */
672 if( t
->i_seekpoint
<= 1 )
674 var_Destroy( p_input
, "next-chapter" );
675 var_Destroy( p_input
, "prev-chapter" );
677 else if( var_Type( p_input
, "next-chapter" ) == 0 )
679 var_Create( p_input
, "next-chapter", VLC_VAR_VOID
);
680 var_Change( p_input
, "next-chapter", VLC_VAR_SETTEXT
,
682 var_AddCallback( p_input
, "next-chapter", SeekpointCallback
, NULL
);
684 var_Create( p_input
, "prev-chapter", VLC_VAR_VOID
);
685 var_Change( p_input
, "prev-chapter", VLC_VAR_SETTEXT
,
686 _("Previous chapter") );
687 var_AddCallback( p_input
, "prev-chapter", SeekpointCallback
, NULL
);
690 /* Build chapter list */
691 var_Change( p_input
, "chapter", VLC_VAR_CLEARCHOICES
);
692 for( i
= 0; i
< t
->i_seekpoint
; i
++ )
697 if( t
->seekpoint
[i
]->psz_name
== NULL
||
698 *t
->seekpoint
[i
]->psz_name
== '\0' )
701 if( asprintf( &text
.psz_string
, _("Chapter %i"),
702 i
+ input_priv(p_input
)->i_seekpoint_offset
) == -1 )
707 text
.psz_string
= strdup( t
->seekpoint
[i
]->psz_name
);
710 var_Change( p_input
, "chapter", VLC_VAR_ADDCHOICE
, val
,
711 (const char *)text
.psz_string
);
712 free( text
.psz_string
);
716 /*****************************************************************************
717 * input_ConfigVarInit:
718 * Create all config object variables
719 *****************************************************************************/
720 void input_ConfigVarInit ( input_thread_t
*p_input
)
722 /* Create Object Variables for private use only */
724 if( !input_priv(p_input
)->b_preparsing
)
726 var_Create( p_input
, "video", VLC_VAR_BOOL
| VLC_VAR_DOINHERIT
);
727 var_Create( p_input
, "audio", VLC_VAR_BOOL
| VLC_VAR_DOINHERIT
);
728 var_Create( p_input
, "spu", VLC_VAR_BOOL
| VLC_VAR_DOINHERIT
);
730 var_Create( p_input
, "video-track", VLC_VAR_INTEGER
|VLC_VAR_DOINHERIT
);
731 var_Create( p_input
, "audio-track", VLC_VAR_INTEGER
|VLC_VAR_DOINHERIT
);
732 var_Create( p_input
, "sub-track", VLC_VAR_INTEGER
|VLC_VAR_DOINHERIT
);
734 var_Create( p_input
, "audio-language",
735 VLC_VAR_STRING
|VLC_VAR_DOINHERIT
);
736 var_Create( p_input
, "sub-language",
737 VLC_VAR_STRING
|VLC_VAR_DOINHERIT
);
738 var_Create( p_input
, "menu-language",
739 VLC_VAR_STRING
|VLC_VAR_DOINHERIT
);
741 var_Create( p_input
, "video-track-id",
742 VLC_VAR_INTEGER
|VLC_VAR_DOINHERIT
);
743 var_Create( p_input
, "audio-track-id",
744 VLC_VAR_INTEGER
|VLC_VAR_DOINHERIT
);
745 var_Create( p_input
, "sub-track-id",
746 VLC_VAR_INTEGER
|VLC_VAR_DOINHERIT
);
748 var_Create( p_input
, "sub-file", VLC_VAR_STRING
| VLC_VAR_DOINHERIT
);
749 var_Create( p_input
, "sub-autodetect-file", VLC_VAR_BOOL
|
751 var_Create( p_input
, "sub-autodetect-path", VLC_VAR_STRING
|
753 var_Create( p_input
, "sub-autodetect-fuzzy", VLC_VAR_INTEGER
|
756 var_Create( p_input
, "sout", VLC_VAR_STRING
| VLC_VAR_DOINHERIT
);
757 var_Create( p_input
, "sout-all", VLC_VAR_BOOL
| VLC_VAR_DOINHERIT
);
758 var_Create( p_input
, "sout-audio", VLC_VAR_BOOL
| VLC_VAR_DOINHERIT
);
759 var_Create( p_input
, "sout-video", VLC_VAR_BOOL
| VLC_VAR_DOINHERIT
);
760 var_Create( p_input
, "sout-spu", VLC_VAR_BOOL
| VLC_VAR_DOINHERIT
);
761 var_Create( p_input
, "sout-keep", VLC_VAR_BOOL
| VLC_VAR_DOINHERIT
);
763 var_Create( p_input
, "input-repeat",
764 VLC_VAR_INTEGER
|VLC_VAR_DOINHERIT
);
765 var_Create( p_input
, "start-time", VLC_VAR_FLOAT
|VLC_VAR_DOINHERIT
);
766 var_Create( p_input
, "stop-time", VLC_VAR_FLOAT
|VLC_VAR_DOINHERIT
);
767 var_Create( p_input
, "run-time", VLC_VAR_FLOAT
|VLC_VAR_DOINHERIT
);
768 var_Create( p_input
, "input-fast-seek", VLC_VAR_BOOL
|VLC_VAR_DOINHERIT
);
770 var_Create( p_input
, "input-slave",
771 VLC_VAR_STRING
| VLC_VAR_DOINHERIT
);
773 var_Create( p_input
, "audio-desync",
774 VLC_VAR_INTEGER
| VLC_VAR_DOINHERIT
);
775 var_Create( p_input
, "cr-average",
776 VLC_VAR_INTEGER
| VLC_VAR_DOINHERIT
);
777 var_Create( p_input
, "clock-synchro",
778 VLC_VAR_INTEGER
| VLC_VAR_DOINHERIT
);
780 var_Create( p_input
, "bookmarks", VLC_VAR_STRING
| VLC_VAR_DOINHERIT
);
781 var_Create( p_input
, "programs", VLC_VAR_STRING
| VLC_VAR_DOINHERIT
);
782 var_Create( p_input
, "program", VLC_VAR_INTEGER
| VLC_VAR_DOINHERIT
);
783 var_Create( p_input
, "rate", VLC_VAR_FLOAT
| VLC_VAR_DOINHERIT
);
787 var_Create( p_input
, "input-record-native", VLC_VAR_BOOL
| VLC_VAR_DOINHERIT
);
790 var_Create( p_input
, "access", VLC_VAR_STRING
| VLC_VAR_DOINHERIT
);
791 var_Create( p_input
, "demux", VLC_VAR_STRING
| VLC_VAR_DOINHERIT
);
792 var_Create( p_input
, "demux-filter", VLC_VAR_STRING
| VLC_VAR_DOINHERIT
);
793 var_Create( p_input
, "stream-filter", VLC_VAR_STRING
| VLC_VAR_DOINHERIT
);
796 var_Create( p_input
, "meta-title", VLC_VAR_STRING
| VLC_VAR_DOINHERIT
);
797 var_Create( p_input
, "meta-author", VLC_VAR_STRING
| VLC_VAR_DOINHERIT
);
798 var_Create( p_input
, "meta-artist", VLC_VAR_STRING
| VLC_VAR_DOINHERIT
);
799 var_Create( p_input
, "meta-genre", VLC_VAR_STRING
| VLC_VAR_DOINHERIT
);
800 var_Create( p_input
, "meta-copyright", VLC_VAR_STRING
| VLC_VAR_DOINHERIT
);
801 var_Create( p_input
, "meta-description", VLC_VAR_STRING
|VLC_VAR_DOINHERIT
);
802 var_Create( p_input
, "meta-date", VLC_VAR_STRING
| VLC_VAR_DOINHERIT
);
803 var_Create( p_input
, "meta-url", VLC_VAR_STRING
| VLC_VAR_DOINHERIT
);
805 /* Inherited by demux/subtitle.c */
806 var_Create( p_input
, "sub-original-fps", VLC_VAR_FLOAT
);
809 /*****************************************************************************
810 * Callbacks managements:
811 *****************************************************************************/
812 static void InputAddCallbacks( input_thread_t
*p_input
,
813 const vlc_input_callback_t
*p_callbacks
)
816 for( i
= 0; p_callbacks
[i
].psz_name
!= NULL
; i
++ )
817 var_AddCallback( p_input
,
818 p_callbacks
[i
].psz_name
,
819 p_callbacks
[i
].callback
, NULL
);
822 /*****************************************************************************
824 *****************************************************************************/
825 static int StateCallback( vlc_object_t
*p_this
, char const *psz_cmd
,
826 vlc_value_t oldval
, vlc_value_t newval
,
829 input_thread_t
*p_input
= (input_thread_t
*)p_this
;
830 VLC_UNUSED(psz_cmd
); VLC_UNUSED(oldval
); VLC_UNUSED(p_data
);
832 if( newval
.i_int
== PLAYING_S
|| newval
.i_int
== PAUSE_S
)
834 input_ControlPushHelper( p_input
, INPUT_CONTROL_SET_STATE
, &newval
);
841 static int RateCallback( vlc_object_t
*p_this
, char const *psz_cmd
,
842 vlc_value_t oldval
, vlc_value_t newval
, void *p_data
)
844 input_thread_t
*p_input
= (input_thread_t
*)p_this
;
845 VLC_UNUSED(oldval
); VLC_UNUSED(p_data
); VLC_UNUSED(psz_cmd
);
847 input_ControlPushHelper( p_input
, INPUT_CONTROL_SET_RATE
, &newval
);
852 static int PositionCallback( vlc_object_t
*p_this
, char const *psz_cmd
,
853 vlc_value_t oldval
, vlc_value_t newval
,
856 input_thread_t
*p_input
= (input_thread_t
*)p_this
;
858 VLC_UNUSED(psz_cmd
); VLC_UNUSED(oldval
); VLC_UNUSED(p_data
);
860 /* Update "length" for better intf behaviour */
861 const vlc_tick_t i_length
= var_GetInteger( p_input
, "length" );
862 if( i_length
> 0 && newval
.f_float
>= 0.f
&& newval
.f_float
<= 1.f
)
866 val
.i_int
= i_length
* newval
.f_float
;
867 var_Change( p_input
, "time", VLC_VAR_SETVALUE
, val
);
870 input_SetPosition( p_input
, newval
.f_float
,
871 var_GetBool( p_input
, "input-fast-seek" ) );
875 static int TimeCallback( vlc_object_t
*p_this
, char const *psz_cmd
,
876 vlc_value_t oldval
, vlc_value_t newval
, void *p_data
)
878 input_thread_t
*p_input
= (input_thread_t
*)p_this
;
879 VLC_UNUSED(psz_cmd
); VLC_UNUSED(oldval
); VLC_UNUSED(p_data
);
881 /* Update "position" for better intf behaviour */
882 const vlc_tick_t i_length
= var_GetInteger( p_input
, "length" );
883 if( i_length
> 0 && newval
.i_int
>= 0 && newval
.i_int
<= i_length
)
887 val
.f_float
= (double)newval
.i_int
/(double)i_length
;
888 var_Change( p_input
, "position", VLC_VAR_SETVALUE
, val
);
890 * Notify the intf that a new event has been occurred.
891 * XXX this is a bit hackish but it's the only way to do it now.
893 var_SetInteger( p_input
, "intf-event", INPUT_EVENT_POSITION
);
896 input_SetTime( p_input
, newval
.i_int
,
897 var_GetBool( p_input
, "input-fast-seek" ) );
901 static int TimeOffsetCallback( vlc_object_t
*obj
, char const *varname
,
902 vlc_value_t prev
, vlc_value_t cur
, void *data
)
904 VLC_UNUSED(varname
); VLC_UNUSED(prev
); VLC_UNUSED(data
);
906 vlc_tick_t i_time
= var_GetInteger( obj
, "time" ) + cur
.i_int
;
909 var_SetInteger( obj
, "time", i_time
);
913 static int ProgramCallback( vlc_object_t
*p_this
, char const *psz_cmd
,
914 vlc_value_t oldval
, vlc_value_t newval
,
917 input_thread_t
*p_input
= (input_thread_t
*)p_this
;
918 VLC_UNUSED(psz_cmd
); VLC_UNUSED(oldval
); VLC_UNUSED(p_data
);
920 input_ControlPushHelper( p_input
, INPUT_CONTROL_SET_PROGRAM
, &newval
);
925 static int TitleCallback( vlc_object_t
*p_this
, char const *psz_cmd
,
926 vlc_value_t oldval
, vlc_value_t newval
,
929 input_thread_t
*p_input
= (input_thread_t
*)p_this
;
932 VLC_UNUSED(oldval
); VLC_UNUSED(p_data
);
934 if( !strcmp( psz_cmd
, "next-title" ) )
936 input_ControlPushHelper( p_input
, INPUT_CONTROL_SET_TITLE_NEXT
, NULL
);
938 val
.i_int
= var_GetInteger( p_input
, "title" ) + 1;
939 var_Change( p_input
, "title", VLC_VAR_CHOICESCOUNT
, &count
);
940 if( (size_t)val
.i_int
< count
)
941 var_Change( p_input
, "title", VLC_VAR_SETVALUE
, val
);
943 else if( !strcmp( psz_cmd
, "prev-title" ) )
945 input_ControlPushHelper( p_input
, INPUT_CONTROL_SET_TITLE_PREV
, NULL
);
947 val
.i_int
= var_GetInteger( p_input
, "title" ) - 1;
949 var_Change( p_input
, "title", VLC_VAR_SETVALUE
, val
);
951 else if( !strcmp( psz_cmd
, "menu-title" ) )
953 input_ControlPushHelper( p_input
, INPUT_CONTROL_NAV_MENU
, NULL
);
955 else if( !strcmp( psz_cmd
, "menu-popup" ) )
957 input_ControlPushHelper( p_input
, INPUT_CONTROL_NAV_POPUP
, NULL
);
961 input_ControlPushHelper( p_input
, INPUT_CONTROL_SET_TITLE
, &newval
);
967 static int SeekpointCallback( vlc_object_t
*p_this
, char const *psz_cmd
,
968 vlc_value_t oldval
, vlc_value_t newval
,
971 input_thread_t
*p_input
= (input_thread_t
*)p_this
;
974 VLC_UNUSED(oldval
); VLC_UNUSED(p_data
);
976 if( !strcmp( psz_cmd
, "next-chapter" ) )
978 input_ControlPushHelper( p_input
, INPUT_CONTROL_SET_SEEKPOINT_NEXT
, NULL
);
980 val
.i_int
= var_GetInteger( p_input
, "chapter" ) + 1;
981 var_Change( p_input
, "chapter", VLC_VAR_CHOICESCOUNT
, &count
);
982 if( (size_t)val
.i_int
< count
)
983 var_Change( p_input
, "chapter", VLC_VAR_SETVALUE
, val
);
985 else if( !strcmp( psz_cmd
, "prev-chapter" ) )
987 input_ControlPushHelper( p_input
, INPUT_CONTROL_SET_SEEKPOINT_PREV
, NULL
);
989 val
.i_int
= var_GetInteger( p_input
, "chapter" ) - 1;
991 var_Change( p_input
, "chapter", VLC_VAR_SETVALUE
, val
);
995 input_ControlPushHelper( p_input
, INPUT_CONTROL_SET_SEEKPOINT
, &newval
);
1001 static int NavigationCallback( vlc_object_t
*p_this
, char const *psz_cmd
,
1002 vlc_value_t oldval
, vlc_value_t newval
,
1005 input_thread_t
*p_input
= (input_thread_t
*)p_this
;
1007 VLC_UNUSED(psz_cmd
); VLC_UNUSED(oldval
);
1009 /* Issue a title change */
1010 sscanf(psz_cmd
, "title %"SCNu64
, &val
.i_int
);
1011 input_ControlPushHelper( p_input
, INPUT_CONTROL_SET_TITLE
, &val
);
1013 var_Change( p_input
, "title", VLC_VAR_SETVALUE
, val
);
1015 /* And a chapter change */
1016 input_ControlPushHelper( p_input
, INPUT_CONTROL_SET_SEEKPOINT
, &newval
);
1018 var_Change( p_input
, "chapter", VLC_VAR_SETVALUE
, newval
);
1023 static int EsVideoCallback( vlc_object_t
*p_this
, char const *psz_cmd
,
1024 vlc_value_t oldval
, vlc_value_t newval
, void *p_data
)
1026 input_thread_t
*p_input
= (input_thread_t
*)p_this
;
1027 VLC_UNUSED( psz_cmd
); VLC_UNUSED( oldval
); VLC_UNUSED( p_data
);
1029 if( newval
.i_int
< 0 )
1030 newval
.i_int
= -VIDEO_ES
; /* disable video es */
1032 input_ControlPushHelper( p_input
, INPUT_CONTROL_SET_ES_BY_ID
, &newval
);
1037 static int EsAudioCallback( vlc_object_t
*p_this
, char const *psz_cmd
,
1038 vlc_value_t oldval
, vlc_value_t newval
, void *p_data
)
1040 input_thread_t
*p_input
= (input_thread_t
*)p_this
;
1041 VLC_UNUSED( psz_cmd
); VLC_UNUSED( oldval
); VLC_UNUSED( p_data
);
1043 if( newval
.i_int
< 0 )
1044 newval
.i_int
= -AUDIO_ES
; /* disable audio es */
1046 input_ControlPushHelper( p_input
, INPUT_CONTROL_SET_ES_BY_ID
, &newval
);
1051 static int EsSpuCallback( vlc_object_t
*p_this
, char const *psz_cmd
,
1052 vlc_value_t oldval
, vlc_value_t newval
, void *p_data
)
1054 input_thread_t
*p_input
= (input_thread_t
*)p_this
;
1055 VLC_UNUSED( psz_cmd
); VLC_UNUSED( oldval
); VLC_UNUSED( p_data
);
1057 if( newval
.i_int
< 0 )
1058 newval
.i_int
= -SPU_ES
; /* disable spu es */
1060 input_ControlPushHelper( p_input
, INPUT_CONTROL_SET_ES_BY_ID
, &newval
);
1065 static int EsDelayCallback ( vlc_object_t
*p_this
, char const *psz_cmd
,
1066 vlc_value_t oldval
, vlc_value_t newval
, void *p_data
)
1068 input_thread_t
*p_input
= (input_thread_t
*)p_this
;
1069 VLC_UNUSED(oldval
); VLC_UNUSED(p_data
);
1071 input_control_param_t param
= {
1074 .i_val
= newval
.i_int
,
1077 if( !strcmp( psz_cmd
, "audio-delay" ) )
1078 input_ControlPush( p_input
, INPUT_CONTROL_SET_AUDIO_DELAY
, ¶m
);
1079 else if( !strcmp( psz_cmd
, "spu-delay" ) )
1080 input_ControlPush( p_input
, INPUT_CONTROL_SET_SPU_DELAY
, ¶m
);
1084 static int BookmarkCallback( vlc_object_t
*p_this
, char const *psz_cmd
,
1085 vlc_value_t oldval
, vlc_value_t newval
,
1088 input_thread_t
*p_input
= (input_thread_t
*)p_this
;
1089 VLC_UNUSED(psz_cmd
); VLC_UNUSED(oldval
); VLC_UNUSED(p_data
);
1091 input_ControlPushHelper( p_input
, INPUT_CONTROL_SET_BOOKMARK
, &newval
);
1096 static int RecordCallback( vlc_object_t
*p_this
, char const *psz_cmd
,
1097 vlc_value_t oldval
, vlc_value_t newval
,
1100 input_thread_t
*p_input
= (input_thread_t
*)p_this
;
1101 VLC_UNUSED(psz_cmd
); VLC_UNUSED(oldval
); VLC_UNUSED(p_data
);
1103 input_ControlPushHelper( p_input
, INPUT_CONTROL_SET_RECORD_STATE
, &newval
);
1108 static int FrameNextCallback( vlc_object_t
*p_this
, char const *psz_cmd
,
1109 vlc_value_t oldval
, vlc_value_t newval
,
1112 input_thread_t
*p_input
= (input_thread_t
*)p_this
;
1113 VLC_UNUSED(psz_cmd
); VLC_UNUSED(oldval
); VLC_UNUSED(p_data
);
1116 input_ControlPushHelper( p_input
, INPUT_CONTROL_SET_FRAME_NEXT
, NULL
);
1121 static int SubFpsCallback( vlc_object_t
*p_this
, char const *psz_cmd
,
1122 vlc_value_t oldval
, vlc_value_t newval
,
1125 input_thread_t
*p_input
= (input_thread_t
*)p_this
;
1126 VLC_UNUSED(psz_cmd
); VLC_UNUSED(oldval
); VLC_UNUSED(p_data
);
1129 input_ControlPushHelper( p_input
, INPUT_CONTROL_SET_SUBS_FPS
, &newval
);