gui: macos: use float for rate
[vlc.git] / src / input / var.c
blob7822d660033e6be5b273b2d5335a714a507acd5a
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 /*****************************************************************************
24 * Preamble
25 *****************************************************************************/
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
30 #include <vlc_common.h>
31 #include <vlc_memstream.h>
32 #include <assert.h>
33 #include <math.h>
34 #include <stdio.h>
35 #include <stdlib.h>
37 #include "input_internal.h"
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 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,
74 void *p_data );
75 static int FrameNextCallback( vlc_object_t *p_this, char const *psz_cmd,
76 vlc_value_t oldval, vlc_value_t newval,
77 void *p_data );
78 static int SubFpsCallback( vlc_object_t *p_this, char const *psz_cmd,
79 vlc_value_t oldval, vlc_value_t newval,
80 void *p_data );
81 static void input_LegacyVarTitle( input_thread_t *p_input, int i_title );
82 static void input_LegacyVarNavigation( input_thread_t *p_input );
84 typedef struct
86 const char *psz_name;
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 */
94 #endif
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 )
119 #undef CALLBACK
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 )
129 vlc_value_t val;
131 val.i_int = i_value;
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,
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 static void VarListSelect( input_thread_t *p_input,
152 const char *psz_variable,
153 int i_value )
155 vlc_value_t val;
157 val.i_int = i_value;
158 var_Change( p_input, psz_variable, VLC_VAR_SETVALUE, val );
160 static const char *GetEsVarName( enum es_format_category_e i_cat )
162 switch( i_cat )
164 case VIDEO_ES:
165 return "video-es";
166 case AUDIO_ES:
167 return "audio-es";
168 case SPU_ES:
169 return "spu-es";
170 default:
171 return NULL;
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 );
204 return;
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 ) )
220 ++option;
221 else
223 free( *option );
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
227 * depend on it) */
228 memmove( option, option + 1, ( --end - option ) * sizeof *end );
232 if( end != orig_end ) /* we removed at least 1 option */
234 *end = vstr.ptr;
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 );
242 free( vstr.ptr );
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 )
254 (void) user_data;
255 vlc_value_t val;
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 );
262 break;
263 case INPUT_EVENT_DEAD:
264 break;
265 case INPUT_EVENT_RATE:
266 val.f_float = event->rate;
267 var_Change( p_input, "rate", VLC_VAR_SETVALUE, val );
268 break;
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 );
280 break;
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 );
286 break;
287 case INPUT_EVENT_LENGTH:
288 /* FIXME ugly + what about meta change event ? */
289 if( var_GetInteger( p_input, "length" ) == event->length )
290 return;
291 val.i_int = event->length;
292 var_Change( p_input, "length", VLC_VAR_SETVALUE, val );
293 break;
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 );
299 break;
300 case INPUT_EVENT_CHAPTER:
301 /* "chapter" */
302 val.i_int = event->chapter.seekpoint;
303 var_Change( p_input, "chapter", VLC_VAR_SETVALUE, val );
305 /* "title %2u" */
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 );
309 break;
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 );
316 break;
317 case VLC_INPUT_PROGRAM_DELETED:
318 VarListDel( p_input, "program", event->program.id );
319 break;
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 );
324 break;
325 case VLC_INPUT_PROGRAM_SELECTED:
326 VarListSelect( p_input, "program", event->program.id );
327 break;
328 case VLC_INPUT_PROGRAM_SCRAMBLED:
329 if( var_GetInteger( p_input, "program" ) != event->program.id )
330 return;
331 var_SetBool( p_input, "program-scrambled", event->program.scrambled );
332 break;
334 break;
335 case INPUT_EVENT_ES:
336 switch (event->es.action)
338 case VLC_INPUT_ES_ADDED:
340 const char *varname = GetEsVarName( event->es.fmt->i_cat );
341 if( varname )
343 size_t count;
344 var_Change( p_input, varname, VLC_VAR_CHOICESCOUNT, &count );
345 if( count == 0 )
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 ) )
355 char psz_page[3+1];
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 : "" );
362 break;
364 case VLC_INPUT_ES_DELETED:
366 const char *varname = GetEsVarName( event->es.fmt->i_cat );
367 if( varname )
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 );
372 break;
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 );
380 if( varname )
381 VarListSelect( p_input, varname, i_id );
382 if( EsFmtIsTeletext( event->es.fmt ) )
383 VarListSelect( p_input, "teletext-es", i_id );
384 break;
386 case VLC_INPUT_ES_UPDATED:
387 break;
389 break;
390 case INPUT_EVENT_RECORD:
391 val.b_bool = event->record;
392 var_Change( p_input, "record", VLC_VAR_SETVALUE, val );
393 break;
394 case INPUT_EVENT_ITEM_META:
395 break;
396 case INPUT_EVENT_ITEM_INFO:
397 break;
398 case INPUT_EVENT_ITEM_EPG:
399 break;
400 case INPUT_EVENT_STATISTICS:
401 break;
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 );
407 break;
408 case INPUT_EVENT_AUDIO_DELAY:
409 val.i_int = event->audio_delay;
410 var_Change( p_input, "audio-delay", VLC_VAR_SETVALUE, val );
411 break;
412 case INPUT_EVENT_SUBTITLE_DELAY:
413 val.i_int = event->subtitle_delay;
414 var_Change( p_input, "spu-delay", VLC_VAR_SETVALUE, val );
415 break;
416 case INPUT_EVENT_BOOKMARK:
417 UpdateBookmarksOption( p_input );
418 break;
419 case INPUT_EVENT_CACHE:
420 val.f_float = event->cache;
421 var_Change( p_input, "cache", VLC_VAR_SETVALUE, val );
422 break;
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:
429 break;
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 )
440 vlc_value_t val;
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 );
475 /* State */
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 );
482 /* Position */
483 var_Create( p_input, "position", VLC_VAR_FLOAT );
485 /* Time */
486 var_Create( p_input, "time", VLC_VAR_INTEGER );
487 var_Create( p_input, "time-offset", VLC_VAR_INTEGER ); /* relative */
489 /* Bookmark */
490 var_Create( p_input, "bookmark", VLC_VAR_INTEGER | VLC_VAR_ISCOMMAND );
491 var_Change( p_input, "bookmark", VLC_VAR_SETTEXT, _("Bookmark") );
493 /* Program */
494 var_Get( p_input, "program", &val );
495 if( val.i_int <= 0 )
496 var_Change( p_input, "program", VLC_VAR_DELCHOICE, val );
497 var_Change( p_input, "program", VLC_VAR_SETTEXT, _("Program") );
499 /* Programs */
500 var_Change( p_input, "programs", VLC_VAR_SETTEXT, _("Programs") );
502 /* Title */
503 var_Create( p_input, "title", VLC_VAR_INTEGER );
504 var_Change( p_input, "title", VLC_VAR_SETTEXT, _("Title") );
506 /* Chapter */
507 var_Create( p_input, "chapter", VLC_VAR_INTEGER );
508 var_Change( p_input, "chapter", VLC_VAR_SETTEXT, _("Chapter") );
510 /* Delay */
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 );
516 val.i_int = -1;
517 /* Video ES */
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") );
522 /* Audio ES */
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") );
527 /* Spu ES */
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 );
544 /* Add all callbacks
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,
563 _("Next title") );
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,
577 _("Menu title") );
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,
584 _("Menu popup") );
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, "]" );
610 else
611 psz_length[0] = '\0';
613 char *titlestr;
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 )
619 continue;
621 else
623 if( asprintf( &titlestr, "%s%s",
624 input_priv(p_input)->title[i]->psz_name, psz_length ) == -1 )
625 continue;
628 /* Add title choice */
629 val2.i_int = i;
630 var_Change( p_input, "title", VLC_VAR_ADDCHOICE, val2,
631 (const char *)titlestr );
633 free( titlestr );
635 for( int j = 0; j < input_priv(p_input)->title[i]->i_seekpoint; j++ )
637 val2.i_int = 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' )
642 /* Default value */
643 if( asprintf( &text2.psz_string, _("Chapter %i"),
644 j + input_priv(p_input)->i_seekpoint_offset ) == -1 )
645 continue;
647 else
649 text2.psz_string =
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];
668 vlc_value_t text;
669 int i;
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,
681 _("Next chapter") );
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++ )
694 vlc_value_t val;
695 val.i_int = i;
697 if( t->seekpoint[i]->psz_name == NULL ||
698 *t->seekpoint[i]->psz_name == '\0' )
700 /* Default value */
701 if( asprintf( &text.psz_string, _("Chapter %i"),
702 i + input_priv(p_input)->i_seekpoint_offset ) == -1 )
703 continue;
705 else
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 |
750 VLC_VAR_DOINHERIT );
751 var_Create( p_input, "sub-autodetect-path", VLC_VAR_STRING |
752 VLC_VAR_DOINHERIT );
753 var_Create( p_input, "sub-autodetect-fuzzy", VLC_VAR_INTEGER |
754 VLC_VAR_DOINHERIT );
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 );
786 /* */
787 var_Create( p_input, "input-record-native", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
789 /* */
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 );
795 /* Meta */
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 )
815 int i;
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 /*****************************************************************************
823 * All Callbacks:
824 *****************************************************************************/
825 static int StateCallback( 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;
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 );
835 return VLC_SUCCESS;
838 return VLC_EGENERIC;
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 );
849 return VLC_SUCCESS;
852 static int PositionCallback( vlc_object_t *p_this, char const *psz_cmd,
853 vlc_value_t oldval, vlc_value_t newval,
854 void *p_data )
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 )
864 vlc_value_t val;
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" ) );
872 return VLC_SUCCESS;
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 )
885 vlc_value_t val;
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" ) );
898 return VLC_SUCCESS;
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;
907 if( i_time < 0 )
908 i_time = 0;
909 var_SetInteger( obj, "time", i_time );
910 return VLC_SUCCESS;
913 static int ProgramCallback( vlc_object_t *p_this, char const *psz_cmd,
914 vlc_value_t oldval, vlc_value_t newval,
915 void *p_data )
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 );
922 return VLC_SUCCESS;
925 static int TitleCallback( vlc_object_t *p_this, char const *psz_cmd,
926 vlc_value_t oldval, vlc_value_t newval,
927 void *p_data )
929 input_thread_t *p_input = (input_thread_t*)p_this;
930 vlc_value_t val;
931 size_t count;
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;
948 if( val.i_int >= 0 )
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 );
959 else
961 input_ControlPushHelper( p_input, INPUT_CONTROL_SET_TITLE, &newval );
964 return VLC_SUCCESS;
967 static int SeekpointCallback( vlc_object_t *p_this, char const *psz_cmd,
968 vlc_value_t oldval, vlc_value_t newval,
969 void *p_data )
971 input_thread_t *p_input = (input_thread_t*)p_this;
972 vlc_value_t val;
973 size_t count;
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;
990 if( val.i_int >= 0 )
991 var_Change( p_input, "chapter", VLC_VAR_SETVALUE, val );
993 else
995 input_ControlPushHelper( p_input, INPUT_CONTROL_SET_SEEKPOINT, &newval );
998 return VLC_SUCCESS;
1001 static int NavigationCallback( vlc_object_t *p_this, char const *psz_cmd,
1002 vlc_value_t oldval, vlc_value_t newval,
1003 void *p_data )
1005 input_thread_t *p_input = (input_thread_t*)p_this;
1006 vlc_value_t val;
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 );
1019 (void) p_data;
1020 return VLC_SUCCESS;
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 );
1034 return VLC_SUCCESS;
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 );
1048 return VLC_SUCCESS;
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 );
1062 return VLC_SUCCESS;
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 = {
1072 .delay = {
1073 .b_absolute = true,
1074 .i_val = newval.i_int,
1077 if( !strcmp( psz_cmd, "audio-delay" ) )
1078 input_ControlPush( p_input, INPUT_CONTROL_SET_AUDIO_DELAY, &param );
1079 else if( !strcmp( psz_cmd, "spu-delay" ) )
1080 input_ControlPush( p_input, INPUT_CONTROL_SET_SPU_DELAY, &param );
1081 return VLC_SUCCESS;
1084 static int BookmarkCallback( vlc_object_t *p_this, char const *psz_cmd,
1085 vlc_value_t oldval, vlc_value_t newval,
1086 void *p_data )
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 );
1093 return VLC_SUCCESS;
1096 static int RecordCallback( vlc_object_t *p_this, char const *psz_cmd,
1097 vlc_value_t oldval, vlc_value_t newval,
1098 void *p_data )
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 );
1105 return VLC_SUCCESS;
1108 static int FrameNextCallback( vlc_object_t *p_this, char const *psz_cmd,
1109 vlc_value_t oldval, vlc_value_t newval,
1110 void *p_data )
1112 input_thread_t *p_input = (input_thread_t*)p_this;
1113 VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval); VLC_UNUSED(p_data);
1114 VLC_UNUSED(newval);
1116 input_ControlPushHelper( p_input, INPUT_CONTROL_SET_FRAME_NEXT, NULL );
1118 return VLC_SUCCESS;
1121 static int SubFpsCallback( vlc_object_t *p_this, char const *psz_cmd,
1122 vlc_value_t oldval, vlc_value_t newval,
1123 void *p_data )
1125 input_thread_t *p_input = (input_thread_t*)p_this;
1126 VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval); VLC_UNUSED(p_data);
1127 VLC_UNUSED(newval);
1129 input_ControlPushHelper( p_input, INPUT_CONTROL_SET_SUBS_FPS, &newval );
1131 return VLC_SUCCESS;