control.c 21.1 KB
Newer Older
gbazin's avatar
gbazin committed
1
2
3
/*****************************************************************************
 * control.c
 *****************************************************************************
4
 * Copyright (C) 1999-2015 VLC authors and VideoLAN
5
 * $Id$
gbazin's avatar
gbazin committed
6
7
8
 *
 * Authors: Gildas Bazin <gbazin@videolan.org>
 *
Jean-Baptiste Kempf's avatar
LGPL    
Jean-Baptiste Kempf committed
9
10
11
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
gbazin's avatar
gbazin committed
12
13
14
15
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Jean-Baptiste Kempf's avatar
LGPL    
Jean-Baptiste Kempf committed
16
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
gbazin's avatar
gbazin committed
18
 *
Jean-Baptiste Kempf's avatar
LGPL    
Jean-Baptiste Kempf committed
19
20
21
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
gbazin's avatar
gbazin committed
22
23
 *****************************************************************************/

24
25
26
27
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

28
#include <vlc_common.h>
29
30
31

#include <stdio.h>
#include <stdlib.h>
32
#include <assert.h>
gbazin's avatar
gbazin committed
33

Laurent Aimar's avatar
Laurent Aimar committed
34
#include "input_internal.h"
35
#include "event.h"
36
#include "resource.h"
37
#include "es_out.h"
38

gbazin's avatar
gbazin committed
39

40
41
static void UpdateBookmarksOption( input_thread_t * );

gbazin's avatar
gbazin committed
42
43
44
45
46
47
48
/****************************************************************************
 * input_Control
 ****************************************************************************/
/**
 * Control function for inputs.
 * \param p_input input handle
 * \param i_query query type
49
 * \return VLC_SUCCESS if ok
gbazin's avatar
gbazin committed
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
 */
int input_Control( input_thread_t *p_input, int i_query, ...  )
{
    va_list args;
    int     i_result;

    va_start( args, i_query );
    i_result = input_vaControl( p_input, i_query, args );
    va_end( args );

    return i_result;
}

int input_vaControl( input_thread_t *p_input, int i_query, va_list args )
{
65
    input_thread_private_t *priv =input_priv(p_input);
66
    seekpoint_t *p_bkmk, ***ppp_bkmk;
67
68
    int i_bkmk = 0;
    int *pi_bkmk;
69

70
    int i_int, *pi_int;
71
    bool b_bool, *pb_bool;
72
73
    double f, *pf;
    int64_t i_64, *pi_64;
gbazin's avatar
gbazin committed
74

75
76
77
    char *psz;
    vlc_value_t val;

gbazin's avatar
gbazin committed
78
79
    switch( i_query )
    {
80
81
82
        case INPUT_GET_POSITION:
            pf = (double*)va_arg( args, double * );
            *pf = var_GetFloat( p_input, "position" );
Laurent Aimar's avatar
Laurent Aimar committed
83
84
            return VLC_SUCCESS;

85
86
        case INPUT_SET_POSITION:
            f = (double)va_arg( args, double );
Laurent Aimar's avatar
Laurent Aimar committed
87
            return var_SetFloat( p_input, "position", f );
88
89
90

        case INPUT_GET_LENGTH:
            pi_64 = (int64_t*)va_arg( args, int64_t * );
91
            *pi_64 = var_GetInteger( p_input, "length" );
Laurent Aimar's avatar
Laurent Aimar committed
92
93
            return VLC_SUCCESS;

94
95
        case INPUT_GET_TIME:
            pi_64 = (int64_t*)va_arg( args, int64_t * );
96
            *pi_64 = var_GetInteger( p_input, "time" );
Laurent Aimar's avatar
Laurent Aimar committed
97
98
            return VLC_SUCCESS;

99
100
        case INPUT_SET_TIME:
            i_64 = (int64_t)va_arg( args, int64_t );
101
            return var_SetInteger( p_input, "time", i_64 );
102
103
104

        case INPUT_GET_RATE:
            pi_int = (int*)va_arg( args, int * );
105
            *pi_int = INPUT_RATE_DEFAULT / var_GetFloat( p_input, "rate" );
Laurent Aimar's avatar
Laurent Aimar committed
106
107
            return VLC_SUCCESS;

108
109
        case INPUT_SET_RATE:
            i_int = (int)va_arg( args, int );
110
111
            return var_SetFloat( p_input, "rate",
                                 (float)INPUT_RATE_DEFAULT / (float)i_int );
112
113
114
115

        case INPUT_GET_STATE:
            pi_int = (int*)va_arg( args, int * );
            *pi_int = var_GetInteger( p_input, "state" );
Laurent Aimar's avatar
Laurent Aimar committed
116
117
            return VLC_SUCCESS;

118
119
        case INPUT_SET_STATE:
            i_int = (int)va_arg( args, int );
Laurent Aimar's avatar
Laurent Aimar committed
120
            return var_SetInteger( p_input, "state", i_int );
121

122
123
        case INPUT_GET_AUDIO_DELAY:
            pi_64 = (int64_t*)va_arg( args, int64_t * );
124
            *pi_64 = var_GetInteger( p_input, "audio-delay" );
125
            return VLC_SUCCESS;
126

127
128
        case INPUT_GET_SPU_DELAY:
            pi_64 = (int64_t*)va_arg( args, int64_t * );
129
            *pi_64 = var_GetInteger( p_input, "spu-delay" );
130
            return VLC_SUCCESS;
131

132
133
        case INPUT_SET_AUDIO_DELAY:
            i_64 = (int64_t)va_arg( args, int64_t );
134
            return var_SetInteger( p_input, "audio-delay", i_64 );
135

136
137
        case INPUT_SET_SPU_DELAY:
            i_64 = (int64_t)va_arg( args, int64_t );
138
            return var_SetInteger( p_input, "spu-delay", i_64 );
139

140
141
142
143
144
        case INPUT_NAV_ACTIVATE:
        case INPUT_NAV_UP:
        case INPUT_NAV_DOWN:
        case INPUT_NAV_LEFT:
        case INPUT_NAV_RIGHT:
145
        case INPUT_NAV_POPUP:
146
        case INPUT_NAV_MENU:
147
148
149
150
            input_ControlPush( p_input, i_query - INPUT_NAV_ACTIVATE
                               + INPUT_CONTROL_NAV_ACTIVATE, NULL );
            return VLC_SUCCESS;

151
        case INPUT_ADD_INFO:
152
        {
153
154
155
156
            char *psz_cat = (char *)va_arg( args, char * );
            char *psz_name = (char *)va_arg( args, char * );
            char *psz_format = (char *)va_arg( args, char * );

157
            char *psz_value;
Jean-Paul Saman's avatar
Jean-Paul Saman committed
158

159
160
            if( vasprintf( &psz_value, psz_format, args ) == -1 )
                return VLC_EGENERIC;
161

162
163
            int i_ret = input_item_AddInfo( priv->p_item, psz_cat, psz_name,
                                            "%s", psz_value );
ivoire's avatar
ivoire committed
164
            free( psz_value );
165

166
            if( !priv->b_preparsing && !i_ret )
167
168
                input_SendEventMetaInfo( p_input );
            return i_ret;
169
        }
170
171
172
173
174
175
        case INPUT_REPLACE_INFOS:
        case INPUT_MERGE_INFOS:
        {
            info_category_t *p_cat = va_arg( args, info_category_t * );

            if( i_query == INPUT_REPLACE_INFOS )
176
                input_item_ReplaceInfos( priv->p_item, p_cat );
177
            else
178
                input_item_MergeInfos( priv->p_item, p_cat );
179

180
            if( !priv->b_preparsing )
181
182
183
                input_SendEventMetaInfo( p_input );
            return VLC_SUCCESS;
        }
184
185
186
187
188
        case INPUT_DEL_INFO:
        {
            char *psz_cat = (char *)va_arg( args, char * );
            char *psz_name = (char *)va_arg( args, char * );

189
            int i_ret = input_item_DelInfo( priv->p_item, psz_cat, psz_name );
190

191
            if( !priv->b_preparsing && !i_ret )
192
193
                input_SendEventMetaInfo( p_input );
            return i_ret;
194
        }
195
196
197
198
199
        case INPUT_GET_INFO:
        {
            char *psz_cat = (char *)va_arg( args, char * );
            char *psz_name = (char *)va_arg( args, char * );
            char **ppsz_value = (char **)va_arg( args, char ** );
200
            int i_ret = VLC_EGENERIC;
201
202
            *ppsz_value = NULL;

203
204
            *ppsz_value = input_item_GetInfo( priv->p_item, psz_cat,
                                              psz_name );
205
206
207
            return i_ret;
        }

gbazin's avatar
gbazin committed
208
209
210
        case INPUT_ADD_BOOKMARK:
            p_bkmk = (seekpoint_t *)va_arg( args, seekpoint_t * );
            p_bkmk = vlc_seekpoint_Duplicate( p_bkmk );
211

212
            vlc_mutex_lock( &priv->p_item->lock );
gbazin's avatar
gbazin committed
213
214
            if( !p_bkmk->psz_name )
            {
215
                 if( asprintf( &p_bkmk->psz_name, _("Bookmark %i"),
216
                               priv->i_bookmark ) == -1 )
217
                     p_bkmk->psz_name = NULL;
gbazin's avatar
gbazin committed
218
            }
219

220
221
            TAB_APPEND( priv->i_bookmark, priv->pp_bookmark, p_bkmk );
            vlc_mutex_unlock( &priv->p_item->lock );
gbazin's avatar
gbazin committed
222

223
224
            UpdateBookmarksOption( p_input );

225
            return VLC_SUCCESS;
gbazin's avatar
gbazin committed
226

227
        case INPUT_CHANGE_BOOKMARK:
228
229
230
            p_bkmk = (seekpoint_t *)va_arg( args, seekpoint_t * );
            i_bkmk = (int)va_arg( args, int );

231
232
            vlc_mutex_lock( &priv->p_item->lock );
            if( i_bkmk < priv->i_bookmark )
233
            {
234
235
                vlc_seekpoint_Delete( priv->pp_bookmark[i_bkmk] );
                priv->pp_bookmark[i_bkmk] = vlc_seekpoint_Duplicate( p_bkmk );
236
            }
237
            vlc_mutex_unlock( &priv->p_item->lock );
238
239
240
241

            UpdateBookmarksOption( p_input );

            return VLC_SUCCESS;
242

gbazin's avatar
gbazin committed
243
        case INPUT_DEL_BOOKMARK:
244
            i_bkmk = (int)va_arg( args, int );
245

246
247
            vlc_mutex_lock( &priv->p_item->lock );
            if( i_bkmk < priv->i_bookmark )
gbazin's avatar
gbazin committed
248
            {
249
250
                p_bkmk = priv->pp_bookmark[i_bkmk];
                TAB_REMOVE( priv->i_bookmark, priv->pp_bookmark, p_bkmk );
251
252
                vlc_seekpoint_Delete( p_bkmk );

253
                vlc_mutex_unlock( &priv->p_item->lock );
254
255
256

                UpdateBookmarksOption( p_input );

257
                return VLC_SUCCESS;
gbazin's avatar
gbazin committed
258
            }
259
            vlc_mutex_unlock( &priv->p_item->lock );
260
261

            return VLC_EGENERIC;
gbazin's avatar
gbazin committed
262
263
264
265

        case INPUT_GET_BOOKMARKS:
            ppp_bkmk = (seekpoint_t ***)va_arg( args, seekpoint_t *** );
            pi_bkmk = (int *)va_arg( args, int * );
266

267
268
            vlc_mutex_lock( &priv->p_item->lock );
            if( priv->i_bookmark )
gbazin's avatar
gbazin committed
269
270
271
            {
                int i;

272
273
274
                *pi_bkmk = priv->i_bookmark;
                *ppp_bkmk = malloc( sizeof(seekpoint_t *) * priv->i_bookmark );
                for( i = 0; i < priv->i_bookmark; i++ )
gbazin's avatar
gbazin committed
275
276
                {
                    (*ppp_bkmk)[i] =
277
                        vlc_seekpoint_Duplicate( input_priv(p_input)->pp_bookmark[i] );
gbazin's avatar
gbazin committed
278
                }
279

280
                vlc_mutex_unlock( &priv->p_item->lock );
281
                return VLC_SUCCESS;
gbazin's avatar
gbazin committed
282
283
284
285
286
            }
            else
            {
                *ppp_bkmk = NULL;
                *pi_bkmk = 0;
287

288
                vlc_mutex_unlock( &priv->p_item->lock );
289
                return VLC_EGENERIC;
gbazin's avatar
gbazin committed
290
291
292
293
            }
            break;

        case INPUT_CLEAR_BOOKMARKS:
294

295
296
            vlc_mutex_lock( &priv->p_item->lock );
            while( priv->i_bookmark > 0 )
gbazin's avatar
gbazin committed
297
            {
298
                p_bkmk = priv->pp_bookmark[priv->i_bookmark - 1];
gbazin's avatar
gbazin committed
299

300
                TAB_REMOVE( priv->i_bookmark, priv->pp_bookmark, p_bkmk );
301
                vlc_seekpoint_Delete( p_bkmk );
gbazin's avatar
gbazin committed
302
            }
303
            vlc_mutex_unlock( &priv->p_item->lock );
304
305

            UpdateBookmarksOption( p_input );
306
            return VLC_SUCCESS;
gbazin's avatar
gbazin committed
307
308
309

        case INPUT_SET_BOOKMARK:
            i_bkmk = (int)va_arg( args, int );
310

311
312
            val.i_int = i_bkmk;
            input_ControlPush( p_input, INPUT_CONTROL_SET_BOOKMARK, &val );
313

314
            return VLC_SUCCESS;
315

316
317
318
        case INPUT_GET_BOOKMARK:
            p_bkmk = (seekpoint_t *)va_arg( args, seekpoint_t * );

319
320
321
            vlc_mutex_lock( &priv->p_item->lock );
            *p_bkmk = priv->bookmark;
            vlc_mutex_unlock( &priv->p_item->lock );
322
323
            return VLC_SUCCESS;

324
325
326
327
328
        case INPUT_GET_TITLE_INFO:
        {
            input_title_t **p_title = (input_title_t **)va_arg( args, input_title_t ** );
            int *pi_req_title_offset = (int *) va_arg( args, int * );

329
            vlc_mutex_lock( &priv->p_item->lock );
330

331
332
333
            int i_current_title = var_GetInteger( p_input, "title" );
            if ( *pi_req_title_offset < 0 ) /* return current title if -1 */
                *pi_req_title_offset = i_current_title;
334

335
            if( priv->i_title && priv->i_title > *pi_req_title_offset )
336
            {
337
338
                *p_title = vlc_input_title_Duplicate( priv->title[*pi_req_title_offset] );
                vlc_mutex_unlock( &priv->p_item->lock );
339
340
341
342
                return VLC_SUCCESS;
            }
            else
            {
343
                vlc_mutex_unlock( &priv->p_item->lock );
344
345
346
347
                return VLC_EGENERIC;
            }
        }

348
349
        case INPUT_GET_FULL_TITLE_INFO:
        {
350
351
            input_title_t **array;
            unsigned count;
352

353
354
            vlc_mutex_lock( &priv->p_item->lock );
            count = priv->i_title;
355
            array = malloc( count * sizeof (*array) );
356

357
            if( count > 0 && unlikely(array == NULL) )
358
            {
359
                vlc_mutex_unlock( &priv->p_item->lock );
360
361
362
                return VLC_ENOMEM;
            }

363
            for( unsigned i = 0; i < count; i++ )
364
                array[i] = vlc_input_title_Duplicate( priv->title[i] );
365

366
            vlc_mutex_unlock( &priv->p_item->lock );
367

368
369
            *va_arg( args, input_title_t *** ) = array;
            *va_arg( args, int * ) = count;
370
371
372
            return VLC_SUCCESS;
        }

373
374
        case INPUT_GET_SEEKPOINTS:
        {
375
376
            seekpoint_t ***array = va_arg( args, seekpoint_t *** );
            int *pi_title_to_fetch = va_arg( args, int * );
377

378
            vlc_mutex_lock( &priv->p_item->lock );
379
380
381
382

            if ( *pi_title_to_fetch < 0 ) /* query current title if -1 */
                *pi_title_to_fetch = var_GetInteger( p_input, "title" );

383
            if( priv->i_title == 0 || priv->i_title <= *pi_title_to_fetch )
384
            {
385
                vlc_mutex_unlock( &priv->p_item->lock );
386
387
388
                return VLC_EGENERIC;
            }

389
            const input_title_t *p_title = priv->title[*pi_title_to_fetch];
390
391
392
393
394
395
396

            /* set arg2 to the number of seekpoints we found */
            const int i_chapters = p_title->i_seekpoint;
            *pi_title_to_fetch = i_chapters;

            if ( i_chapters == 0 )
            {
397
                vlc_mutex_unlock( &priv->p_item->lock );
398
399
400
401
                return VLC_SUCCESS;
            }

            *array = calloc( p_title->i_seekpoint, sizeof(**array) );
402
            if( unlikely(array == NULL) )
403
            {
404
                vlc_mutex_unlock( &priv->p_item->lock );
405
406
407
408
409
410
411
                return VLC_ENOMEM;
            }
            for( int i = 0; i < i_chapters; i++ )
            {
                (*array)[i] = vlc_seekpoint_Duplicate( p_title->seekpoint[i] );
            }

412
            vlc_mutex_unlock( &priv->p_item->lock );
413
414
415
416

            return VLC_SUCCESS;
        }

417
        case INPUT_ADD_SLAVE:
418
419
        {
            enum slave_type type =  (enum slave_type) va_arg( args, enum slave_type );
420
            psz = (char*)va_arg( args, char * );
421
            b_bool = (bool)va_arg( args, int );
422
423
424
425
426
427
428
429

            if( !psz || ( type != SLAVE_TYPE_SPU && type != SLAVE_TYPE_AUDIO ) )
                return VLC_EGENERIC;

            input_item_slave_t *p_slave =
                input_item_slave_New( psz, type, SLAVE_PRIORITY_USER );
            if( !p_slave )
                return VLC_ENOMEM;
430
            p_slave->b_forced = b_bool;
431
432
433

            val.p_address = p_slave;
            input_ControlPush( p_input, INPUT_CONTROL_ADD_SLAVE, &val );
434
            return VLC_SUCCESS;
435
        }
gbazin's avatar
gbazin committed
436

437
438
439
440
441
442
443
444
445
446
447
448
449
        case INPUT_ADD_SUBTITLE:
            psz = (char*)va_arg( args, char * );
            b_bool = (bool)va_arg( args, int );

            if( !psz || *psz == '\0' )
                return VLC_EGENERIC;
            if( b_bool && !subtitles_Filter( psz ) )
                return VLC_EGENERIC;

            val.psz_string = strdup( psz );
            input_ControlPush( p_input, INPUT_CONTROL_ADD_SUBTITLE, &val );
            return VLC_SUCCESS;

450
451
452
453
454
455
        case INPUT_GET_ATTACHMENTS: /* arg1=input_attachment_t***, arg2=int*  res=can fail */
        {
            input_attachment_t ***ppp_attachment = (input_attachment_t***)va_arg( args, input_attachment_t *** );
            int *pi_attachment = (int*)va_arg( args, int * );
            int i;

456
457
            vlc_mutex_lock( &priv->p_item->lock );
            if( priv->i_attachment <= 0 )
458
            {
459
                vlc_mutex_unlock( &priv->p_item->lock );
460
461
462
463
                *ppp_attachment = NULL;
                *pi_attachment = 0;
                return VLC_EGENERIC;
            }
464
465
466
467
            *pi_attachment = priv->i_attachment;
            *ppp_attachment = malloc( sizeof(input_attachment_t*) * priv->i_attachment );
            for( i = 0; i < priv->i_attachment; i++ )
                (*ppp_attachment)[i] = vlc_input_attachment_Duplicate( priv->attachment[i] );
468

469
            vlc_mutex_unlock( &priv->p_item->lock );
470
            return VLC_SUCCESS;
471
472
473
474
475
476
477
478
        }

        case INPUT_GET_ATTACHMENT:  /* arg1=input_attachment_t**, arg2=char*  res=can fail */
        {
            input_attachment_t **pp_attachment = (input_attachment_t**)va_arg( args, input_attachment_t ** );
            const char *psz_name = (const char*)va_arg( args, const char * );
            int i;

479
480
            vlc_mutex_lock( &priv->p_item->lock );
            for( i = 0; i < priv->i_attachment; i++ )
481
            {
482
                if( !strcmp( priv->attachment[i]->psz_name, psz_name ) )
483
                {
484
485
                    *pp_attachment = vlc_input_attachment_Duplicate(priv->attachment[i] );
                    vlc_mutex_unlock( &priv->p_item->lock );
486
487
488
489
                    return VLC_SUCCESS;
                }
            }
            *pp_attachment = NULL;
490
            vlc_mutex_unlock( &priv->p_item->lock );
491
492
493
            return VLC_EGENERIC;
        }

494
495
496
497
498
499
500
501
502
        case INPUT_SET_RECORD_STATE:
            b_bool = (bool)va_arg( args, int );
            var_SetBool( p_input, "record", b_bool );
            return VLC_SUCCESS;

        case INPUT_GET_RECORD_STATE:
            pb_bool = (bool*)va_arg( args, bool* );
            *pb_bool = var_GetBool( p_input, "record" );
            return VLC_SUCCESS;
503

504
505
506
507
508
        case INPUT_RESTART_ES:
            val.i_int = (int)va_arg( args, int );
            input_ControlPush( p_input, INPUT_CONTROL_RESTART_ES, &val );
            return VLC_SUCCESS;

509
510
511
512
513
514
515
516
517
518
519
520
521
522
        case INPUT_UPDATE_VIEWPOINT:
        {
            vlc_viewpoint_t *p_viewpoint = malloc( sizeof(*p_viewpoint) );
            if( unlikely(p_viewpoint == NULL) )
                return VLC_ENOMEM;
            val.p_address = p_viewpoint;
            *p_viewpoint = *va_arg( args, const vlc_viewpoint_t* );
            if ( va_arg( args, int ) )
                input_ControlPush( p_input, INPUT_CONTROL_SET_VIEWPOINT, &val );
            else
                input_ControlPush( p_input, INPUT_CONTROL_UPDATE_VIEWPOINT, &val );
            return VLC_SUCCESS;
        }

523
524
        case INPUT_GET_AOUT:
        {
525
            audio_output_t *p_aout = input_resource_HoldAout( priv->p_resource );
526
527
528
            if( !p_aout )
                return VLC_EGENERIC;

529
            audio_output_t **pp_aout = (audio_output_t**)va_arg( args, audio_output_t** );
530
531
532
533
534
535
536
            *pp_aout = p_aout;
            return VLC_SUCCESS;
        }

        case INPUT_GET_VOUTS:
        {
            vout_thread_t ***ppp_vout = (vout_thread_t***)va_arg( args, vout_thread_t*** );
537
            size_t        *pi_vout = va_arg( args, size_t * );
538

539
            input_resource_HoldVouts( priv->p_resource, ppp_vout, pi_vout );
540
541
542
543
544
            if( *pi_vout <= 0 )
                return VLC_EGENERIC;
            return VLC_SUCCESS;
        }

545
546
547
548
549
        case INPUT_GET_ES_OBJECTS:
        {
            const int i_id = va_arg( args, int );
            vlc_object_t    **pp_decoder = va_arg( args, vlc_object_t ** );
            vout_thread_t   **pp_vout    = va_arg( args, vout_thread_t ** );
550
            audio_output_t **pp_aout    = va_arg( args, audio_output_t ** );
551

552
553
            return es_out_Control( priv->p_es_out_display,
                                   ES_OUT_GET_ES_OBJECTS_BY_ID, i_id,
554
555
556
                                   pp_decoder, pp_vout, pp_aout );
        }

557
558
559
        case INPUT_GET_PCR_SYSTEM:
        {
            mtime_t *pi_system = va_arg( args, mtime_t * );
560
            mtime_t *pi_delay  = va_arg( args, mtime_t * );
561
            return es_out_ControlGetPcrSystem( priv->p_es_out_display, pi_system, pi_delay );
562
563
564
565
566
567
        }

        case INPUT_MODIFY_PCR_SYSTEM:
        {
            bool b_absolute = va_arg( args, int );
            mtime_t i_system = va_arg( args, mtime_t );
568
            return es_out_ControlModifyPcrSystem( priv->p_es_out_display, b_absolute, i_system );
569
570
        }

gbazin's avatar
gbazin committed
571
572
        default:
            msg_Err( p_input, "unknown query in input_vaControl" );
Laurent Aimar's avatar
Laurent Aimar committed
573
            return VLC_EGENERIC;
gbazin's avatar
gbazin committed
574
575
    }
}
576
577
578

static void UpdateBookmarksOption( input_thread_t *p_input )
{
579
580
581
    input_thread_private_t *priv =input_priv(p_input);

    vlc_mutex_lock( &priv->p_item->lock );
582
583
584

    /* Update the "bookmark" list */
    var_Change( p_input, "bookmark", VLC_VAR_CLEARCHOICES, 0, 0 );
585
    for( int i = 0; i < priv->i_bookmark; i++ )
586
    {
587
        vlc_value_t val, text;
588

589
        val.i_int = i;
590
        text.psz_string = priv->pp_bookmark[i]->psz_name;
591
592
593
594
595
        var_Change( p_input, "bookmark", VLC_VAR_ADDCHOICE,
                    &val, &text );
    }

    /* Create the "bookmarks" option value */
596
    const char *psz_format = "{name=%s,time=%"PRId64"}";
597
    int i_len = strlen( "bookmarks=" );
598
    for( int i = 0; i < priv->i_bookmark; i++ )
599
    {
600
        const seekpoint_t *p_bookmark = priv->pp_bookmark[i];
601
602
603
604
605
606

        i_len += snprintf( NULL, 0, psz_format,
                           p_bookmark->psz_name,
                           p_bookmark->i_time_offset/1000000 );
    }

607
    char *psz_value = malloc( i_len + priv->i_bookmark + 1 );
608

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
609
    if( psz_value != NULL )
610
    {
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
611
        strcpy( psz_value, "bookmarks=" );
612

613
        char *psz_next = psz_value + strlen( "bookmarks=" );
614

615
        for( int i = 0; i < priv->i_bookmark && psz_value != NULL; i++ )
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
616
        {
617
            const seekpoint_t *p_bookmark = priv->pp_bookmark[i];
618

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
619
620
621
            psz_next += sprintf( psz_next, psz_format,
                                 p_bookmark->psz_name,
                                 p_bookmark->i_time_offset/1000000 );
622

623
            if( i < priv->i_bookmark - 1)
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
624
625
626
                *psz_next++ = ',';
        }
    }
627
    vlc_mutex_unlock( &priv->p_item->lock );
628

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
629
630
    if( psz_value != NULL )
    {
631
        input_item_AddOption( priv->p_item, psz_value,
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
632
633
634
                              VLC_INPUT_OPTION_UNIQUE );
        free( psz_value );
    }
635
    input_SendEventBookmark( p_input );
636
}
637