control.c 22.2 KB
Newer Older
gbazin's avatar
gbazin committed
1
2
3
/*****************************************************************************
 * control.c
 *****************************************************************************
4
 * Copyright (C) 1999-2004 the VideoLAN team
5
 * $Id$
gbazin's avatar
gbazin committed
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 *
 * Authors: Gildas Bazin <gbazin@videolan.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (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
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
dionoea's avatar
dionoea committed
21
 * 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

gbazin's avatar
gbazin committed
28
#include <vlc/vlc.h>
29
30
31

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

Laurent Aimar's avatar
Laurent Aimar committed
33
#include "input_internal.h"
34
35
#include "vlc_playlist.h"

gbazin's avatar
gbazin committed
36

37
static void UpdateBookmarksOption( input_thread_t * );
38
static void NotifyPlaylist( input_thread_t * );
39

gbazin's avatar
gbazin committed
40
41
42
43
44
45
46
/****************************************************************************
 * input_Control
 ****************************************************************************/
/**
 * Control function for inputs.
 * \param p_input input handle
 * \param i_query query type
47
 * \return VLC_SUCCESS if ok
gbazin's avatar
gbazin committed
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
 */
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 )
{
63
    seekpoint_t *p_bkmk, ***ppp_bkmk;
64
65
    int i_bkmk = 0;
    int *pi_bkmk;
66

67
68
69
    int i_int, *pi_int;
    double f, *pf;
    int64_t i_64, *pi_64;
gbazin's avatar
gbazin committed
70

71
72
73
    char *psz;
    vlc_value_t val;

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

81
82
        case INPUT_SET_POSITION:
            f = (double)va_arg( args, double );
Laurent Aimar's avatar
Laurent Aimar committed
83
            return var_SetFloat( p_input, "position", f );
84
85
86
87

        case INPUT_GET_LENGTH:
            pi_64 = (int64_t*)va_arg( args, int64_t * );
            *pi_64 = var_GetTime( p_input, "length" );
Laurent Aimar's avatar
Laurent Aimar committed
88
89
            return VLC_SUCCESS;

90
91
92
        case INPUT_GET_TIME:
            pi_64 = (int64_t*)va_arg( args, int64_t * );
            *pi_64 = var_GetTime( p_input, "time" );
Laurent Aimar's avatar
Laurent Aimar committed
93
94
            return VLC_SUCCESS;

95
96
        case INPUT_SET_TIME:
            i_64 = (int64_t)va_arg( args, int64_t );
Laurent Aimar's avatar
Laurent Aimar committed
97
            return var_SetTime( p_input, "time", i_64 );
98
99
100
101

        case INPUT_GET_RATE:
            pi_int = (int*)va_arg( args, int * );
            *pi_int = var_GetInteger( p_input, "rate" );
Laurent Aimar's avatar
Laurent Aimar committed
102
103
            return VLC_SUCCESS;

104
105
        case INPUT_SET_RATE:
            i_int = (int)va_arg( args, int );
Laurent Aimar's avatar
Laurent Aimar committed
106
            return var_SetInteger( p_input, "rate", i_int );
107
108
109
110

        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
111
112
            return VLC_SUCCESS;

113
114
        case INPUT_SET_STATE:
            i_int = (int)va_arg( args, int );
Laurent Aimar's avatar
Laurent Aimar committed
115
            return var_SetInteger( p_input, "state", i_int );
116

117
118
119
120
        case INPUT_GET_AUDIO_DELAY:
            pi_64 = (int64_t*)va_arg( args, int64_t * );
            *pi_64 = var_GetTime( p_input, "audio-delay" );
            return VLC_SUCCESS;
121

122
123
124
125
        case INPUT_GET_SPU_DELAY:
            pi_64 = (int64_t*)va_arg( args, int64_t * );
            *pi_64 = var_GetTime( p_input, "spu-delay" );
            return VLC_SUCCESS;
126

127
128
129
        case INPUT_SET_AUDIO_DELAY:
            i_64 = (int64_t)va_arg( args, int64_t );
            return var_SetTime( p_input, "audio-delay", i_64 );
130

131
132
133
        case INPUT_SET_SPU_DELAY:
            i_64 = (int64_t)va_arg( args, int64_t );
            return var_SetTime( p_input, "spu-delay", i_64 );
134
135

        case INPUT_ADD_INFO:
136
        {
137
            /* FIXME : Impossible to use input_ItemAddInfo because of
138
             * the ... problem ? */
139
140
141
142
            char *psz_cat = (char *)va_arg( args, char * );
            char *psz_name = (char *)va_arg( args, char * );
            char *psz_format = (char *)va_arg( args, char * );

143
            info_category_t *p_cat;
144
            info_t *p_info;
145
            int i;
146

zorglub's avatar
zorglub committed
147
148
            vlc_mutex_lock( &p_input->p->input.p_item->lock );
            for( i = 0; i < p_input->p->input.p_item->i_categories; i++ )
149
            {
zorglub's avatar
zorglub committed
150
                if( !strcmp( p_input->p->input.p_item->pp_categories[i]->psz_name,
151
                             psz_cat ) ) break;
152
153
            }

zorglub's avatar
zorglub committed
154
            if( i == p_input->p->input.p_item->i_categories )
155
156
            {
                p_cat = malloc( sizeof( info_category_t ) );
157
                if( !p_cat )
158
                {
Rafaël Carré's avatar
Rafaël Carré committed
159
                    vlc_mutex_unlock( &p_input->p->input.p_item->lock );
160
                    return VLC_EGENERIC;
161
                }
162
163
164
                p_cat->psz_name = strdup( psz_cat );
                p_cat->i_infos = 0;
                p_cat->pp_infos = NULL;
zorglub's avatar
zorglub committed
165
166
167
                INSERT_ELEM( p_input->p->input.p_item->pp_categories,
                             p_input->p->input.p_item->i_categories,
                             p_input->p->input.p_item->i_categories, p_cat );
168
169
            }

zorglub's avatar
zorglub committed
170
            p_cat = p_input->p->input.p_item->pp_categories[i];
171
172
173
174
175
176
177

            for( i = 0; i < p_cat->i_infos; i++ )
            {
                if( !strcmp( p_cat->pp_infos[i]->psz_name, psz_name ) )
                {
                    if( p_cat->pp_infos[i]->psz_value )
                        free( p_cat->pp_infos[i]->psz_value );
178
                    break;
179
180
181
                }
            }

182
183
184
            if( i == p_cat->i_infos )
            {
                p_info = malloc( sizeof( info_t ) );
185
                if( !p_info )
186
                {
Rafaël Carré's avatar
Rafaël Carré committed
187
                    vlc_mutex_unlock( &p_input->p->input.p_item->lock );
188
                    return VLC_EGENERIC;
189
190
                }

191
192
193
194
                INSERT_ELEM( p_cat->pp_infos, p_cat->i_infos,
                             p_cat->i_infos, p_info );
                p_info->psz_name = strdup( psz_name );
            }
195

196
            p_info = p_cat->pp_infos[i];
197
198
            if( vasprintf( &p_info->psz_value, psz_format, args ) == -1 )
                p_info->psz_value = NULL;
199

zorglub's avatar
zorglub committed
200
            vlc_mutex_unlock( &p_input->p->input.p_item->lock );
201

202
203
            if( !p_input->b_preparsing )
                NotifyPlaylist( p_input );
204
        }
205
        return VLC_SUCCESS;
206

207
208
209
210
211
212
        case INPUT_DEL_INFO:
        {
            char *psz_cat = (char *)va_arg( args, char * );
            char *psz_name = (char *)va_arg( args, char * );

            info_category_t *p_cat = NULL;
213
            int i_cat;
214
215
            int i;

zorglub's avatar
zorglub committed
216
            vlc_mutex_lock( &p_input->p->input.p_item->lock );
217
            for( i_cat = 0; i_cat < p_input->p->input.p_item->i_categories; i_cat++ )
218
            {
219
                if( !strcmp( p_input->p->input.p_item->pp_categories[i_cat]->psz_name,
220
221
                             psz_cat ) )
                {
222
                    p_cat = p_input->p->input.p_item->pp_categories[i_cat];
223
224
225
226
227
                    break;
                }
            }
            if( p_cat == NULL )
            {
zorglub's avatar
zorglub committed
228
                vlc_mutex_unlock( &p_input->p->input.p_item->lock );
229
230
231
                return VLC_EGENERIC;
            }

232
            if( psz_name )
233
            {
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
                /* Remove a specific info */
                for( i = 0; i < p_cat->i_infos; i++ )
                {
                    if( !strcmp( p_cat->pp_infos[i]->psz_name, psz_name ) )
                    {
                        free( p_cat->pp_infos[i]->psz_name );
                        if( p_cat->pp_infos[i]->psz_value )
                            free( p_cat->pp_infos[i]->psz_value );
                        free( p_cat->pp_infos[i] );
                        REMOVE_ELEM( p_cat->pp_infos, p_cat->i_infos, i );
                        break;
                    }
                }
                if( i >= p_cat->i_infos )
                {
                    vlc_mutex_unlock( &p_input->p->input.p_item->lock );
                    return VLC_EGENERIC;
                }
            }
            else
            {
                /* Remove the complete categorie */
                for( i = 0; i < p_cat->i_infos; i++ )
257
                {
258
259
260
261
                    free( p_cat->pp_infos[i]->psz_name );
                    if( p_cat->pp_infos[i]->psz_value )
                        free( p_cat->pp_infos[i]->psz_value );
                    free( p_cat->pp_infos[i] );
262
                }
263
264
265
                if( p_cat->pp_infos )
                    free( p_cat->pp_infos );
                REMOVE_ELEM( p_input->p->input.p_item->pp_categories, p_input->p->input.p_item->i_categories, i_cat );
266
            }
zorglub's avatar
zorglub committed
267
            vlc_mutex_unlock( &p_input->p->input.p_item->lock );
268

269
270
            if( !p_input->b_preparsing )
                NotifyPlaylist( p_input );
271
272

            return VLC_SUCCESS;
273
274
        }

275

276
277
278
279
280
        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 ** );
281
            int i_ret = VLC_EGENERIC;
282
283
            *ppsz_value = NULL;

zorglub's avatar
zorglub committed
284
            *ppsz_value = input_ItemGetInfo( p_input->p->input.p_item,
285
                                                  psz_cat, psz_name );
286
287
288
289
290
291
292
            return i_ret;
        }

        case INPUT_SET_NAME:
        {
            char *psz_name = (char *)va_arg( args, char * );

293
            if( !psz_name ) return VLC_EGENERIC;
294

zorglub's avatar
zorglub committed
295
296
297
298
299
            vlc_mutex_lock( &p_input->p->input.p_item->lock );
            if( p_input->p->input.p_item->psz_name )
                free( p_input->p->input.p_item->psz_name );
            p_input->p->input.p_item->psz_name = strdup( psz_name );
            vlc_mutex_unlock( &p_input->p->input.p_item->lock );
300

301
302
            if( !p_input->b_preparsing )
                NotifyPlaylist( p_input );
303
304

            return VLC_SUCCESS;
305
306
        }

gbazin's avatar
gbazin committed
307
308
309
        case INPUT_ADD_BOOKMARK:
            p_bkmk = (seekpoint_t *)va_arg( args, seekpoint_t * );
            p_bkmk = vlc_seekpoint_Duplicate( p_bkmk );
310

zorglub's avatar
zorglub committed
311
            vlc_mutex_lock( &p_input->p->input.p_item->lock );
gbazin's avatar
gbazin committed
312
313
            if( !p_bkmk->psz_name )
            {
314
315
316
                 if( asprintf( &p_bkmk->psz_name, _("Bookmark %i"),
                               p_input->p->i_bookmark ) == -1 )
                     p_bkmk->psz_name = NULL;
gbazin's avatar
gbazin committed
317
            }
318

zorglub's avatar
zorglub committed
319
            TAB_APPEND( p_input->p->i_bookmark, p_input->p->bookmark, p_bkmk );
gbazin's avatar
gbazin committed
320
321
322
323

            /* Reflect the changes on the object var */
            var_Change( p_input, "bookmark", VLC_VAR_CLEARCHOICES, 0, 0 );
            {
324
                vlc_value_t val, text;
gbazin's avatar
gbazin committed
325
                int i;
326

zorglub's avatar
zorglub committed
327
                for( i = 0; i < p_input->p->i_bookmark; i++ )
gbazin's avatar
gbazin committed
328
329
                {
                    val.i_int = i;
zorglub's avatar
zorglub committed
330
                    text.psz_string = p_input->p->bookmark[i]->psz_name;
gbazin's avatar
gbazin committed
331
332
333
334
                    var_Change( p_input, "bookmark", VLC_VAR_ADDCHOICE,
                                &val, &text );
                }
            }
zorglub's avatar
zorglub committed
335
            vlc_mutex_unlock( &p_input->p->input.p_item->lock );
gbazin's avatar
gbazin committed
336

337
338
            UpdateBookmarksOption( p_input );

339
            return VLC_SUCCESS;
gbazin's avatar
gbazin committed
340

341
        case INPUT_CHANGE_BOOKMARK:
342
343
344
            p_bkmk = (seekpoint_t *)va_arg( args, seekpoint_t * );
            i_bkmk = (int)va_arg( args, int );

zorglub's avatar
zorglub committed
345
346
            vlc_mutex_lock( &p_input->p->input.p_item->lock );
            if( i_bkmk < p_input->p->i_bookmark )
347
348
349
350
            {
                vlc_value_t val, text;
                int i;

zorglub's avatar
zorglub committed
351
                p_input->p->bookmark[i_bkmk] = p_bkmk;
352
353
354

                /* Reflect the changes on the object var */
                var_Change( p_input, "bookmark", VLC_VAR_CLEARCHOICES, 0, 0 );
zorglub's avatar
zorglub committed
355
                for( i = 0; i < p_input->p->i_bookmark; i++ )
356
357
                {
                    val.i_int = i;
zorglub's avatar
zorglub committed
358
                    text.psz_string = p_input->p->bookmark[i]->psz_name;
359
360
361
362
                    var_Change( p_input, "bookmark", VLC_VAR_ADDCHOICE,
                                &val, &text );
                }
            }
zorglub's avatar
zorglub committed
363
            vlc_mutex_unlock( &p_input->p->input.p_item->lock );
364
365
366
367

            UpdateBookmarksOption( p_input );

            return VLC_SUCCESS;
368

gbazin's avatar
gbazin committed
369
        case INPUT_DEL_BOOKMARK:
370
            i_bkmk = (int)va_arg( args, int );
371

zorglub's avatar
zorglub committed
372
373
            vlc_mutex_lock( &p_input->p->input.p_item->lock );
            if( i_bkmk < p_input->p->i_bookmark )
gbazin's avatar
gbazin committed
374
            {
375
                vlc_value_t val, text;
gbazin's avatar
gbazin committed
376
                int i;
377

zorglub's avatar
zorglub committed
378
379
                p_bkmk = p_input->p->bookmark[i_bkmk];
                TAB_REMOVE( p_input->p->i_bookmark, p_input->p->bookmark,
380
381
382
383
384
                            p_bkmk );
                vlc_seekpoint_Delete( p_bkmk );

                /* Reflect the changes on the object var */
                var_Change( p_input, "bookmark", VLC_VAR_CLEARCHOICES, 0, 0 );
zorglub's avatar
zorglub committed
385
                for( i = 0; i < p_input->p->i_bookmark; i++ )
gbazin's avatar
gbazin committed
386
                {
387
                    val.i_int = i;
zorglub's avatar
zorglub committed
388
                    text.psz_string = p_input->p->bookmark[i]->psz_name;
389
390
                    var_Change( p_input, "bookmark", VLC_VAR_ADDCHOICE,
                                &val, &text );
gbazin's avatar
gbazin committed
391
                }
zorglub's avatar
zorglub committed
392
                vlc_mutex_unlock( &p_input->p->input.p_item->lock );
393
394
395

                UpdateBookmarksOption( p_input );

396
                return VLC_SUCCESS;
gbazin's avatar
gbazin committed
397
            }
zorglub's avatar
zorglub committed
398
            vlc_mutex_unlock( &p_input->p->input.p_item->lock );
399
400

            return VLC_EGENERIC;
gbazin's avatar
gbazin committed
401
402
403
404

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

zorglub's avatar
zorglub committed
406
407
            vlc_mutex_lock( &p_input->p->input.p_item->lock );
            if( p_input->p->i_bookmark )
gbazin's avatar
gbazin committed
408
409
410
            {
                int i;

zorglub's avatar
zorglub committed
411
                *pi_bkmk = p_input->p->i_bookmark;
gbazin's avatar
gbazin committed
412
                *ppp_bkmk = malloc( sizeof(seekpoint_t *) *
zorglub's avatar
zorglub committed
413
414
                                    p_input->p->i_bookmark );
                for( i = 0; i < p_input->p->i_bookmark; i++ )
gbazin's avatar
gbazin committed
415
416
                {
                    (*ppp_bkmk)[i] =
zorglub's avatar
zorglub committed
417
                        vlc_seekpoint_Duplicate(p_input->p->bookmark[i]);
gbazin's avatar
gbazin committed
418
                }
419

zorglub's avatar
zorglub committed
420
                vlc_mutex_unlock( &p_input->p->input.p_item->lock );
421
                return VLC_SUCCESS;
gbazin's avatar
gbazin committed
422
423
424
425
426
            }
            else
            {
                *ppp_bkmk = NULL;
                *pi_bkmk = 0;
427

zorglub's avatar
zorglub committed
428
                vlc_mutex_unlock( &p_input->p->input.p_item->lock );
429
                return VLC_EGENERIC;
gbazin's avatar
gbazin committed
430
431
432
433
            }
            break;

        case INPUT_CLEAR_BOOKMARKS:
434

zorglub's avatar
zorglub committed
435
436
            vlc_mutex_lock( &p_input->p->input.p_item->lock );
            if( p_input->p->i_bookmark )
gbazin's avatar
gbazin committed
437
438
439
            {
                int i;

zorglub's avatar
zorglub committed
440
                for( i = p_input->p->i_bookmark - 1; i >= 0; i-- )
gbazin's avatar
gbazin committed
441
                {
zorglub's avatar
zorglub committed
442
443
                    p_bkmk = p_input->p->bookmark[i];
                    TAB_REMOVE( p_input->p->i_bookmark, p_input->p->bookmark,
gbazin's avatar
gbazin committed
444
445
446
                                p_bkmk );
                    vlc_seekpoint_Delete( p_bkmk );
                }
447
                var_Change( p_input, "bookmark", VLC_VAR_CLEARCHOICES, 0, 0 );
gbazin's avatar
gbazin committed
448
            }
zorglub's avatar
zorglub committed
449
            vlc_mutex_unlock( &p_input->p->input.p_item->lock );
450
451
452

            UpdateBookmarksOption( p_input );

453
            return VLC_SUCCESS;
gbazin's avatar
gbazin committed
454
455
456

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

zorglub's avatar
zorglub committed
458
459
            vlc_mutex_lock( &p_input->p->input.p_item->lock );
            if( i_bkmk >= 0 && i_bkmk < p_input->p->i_bookmark )
gbazin's avatar
gbazin committed
460
461
            {
                vlc_value_t pos;
462
463
                int i_ret;

zorglub's avatar
zorglub committed
464
                if( p_input->p->bookmark[i_bkmk]->i_time_offset != -1 )
465
                {
zorglub's avatar
zorglub committed
466
                    pos.i_time = p_input->p->bookmark[i_bkmk]->i_time_offset;
467
468
                    i_ret = var_Set( p_input, "time", pos );
                }
zorglub's avatar
zorglub committed
469
                else if( p_input->p->bookmark[i_bkmk]->i_byte_offset != -1 )
gbazin's avatar
gbazin committed
470
                {
471
                    // don't crash on bookmarks in live streams
zorglub's avatar
zorglub committed
472
                    if( stream_Size( p_input->p->input.p_stream ) == 0 )
473
                    {
zorglub's avatar
zorglub committed
474
                        vlc_mutex_unlock( &p_input->p->input.p_item->lock );
475
476
                        return VLC_EGENERIC;
                    }
zorglub's avatar
zorglub committed
477
478
479
                    pos.f_float = !p_input->p->input.p_stream ? 0 :
                        p_input->p->bookmark[i_bkmk]->i_byte_offset /
                        stream_Size( p_input->p->input.p_stream );
gbazin's avatar
gbazin committed
480
481
                    i_ret = var_Set( p_input, "position", pos );
                }
482
                else
gbazin's avatar
gbazin committed
483
                {
484
485
                    pos.f_float = 0;
                    i_ret = var_Set( p_input, "position", pos );
gbazin's avatar
gbazin committed
486
                }
487

zorglub's avatar
zorglub committed
488
                vlc_mutex_unlock( &p_input->p->input.p_item->lock );
489
                return i_ret;
gbazin's avatar
gbazin committed
490
491
492
            }
            else
            {
zorglub's avatar
zorglub committed
493
                vlc_mutex_unlock( &p_input->p->input.p_item->lock );
494
                return VLC_EGENERIC;
gbazin's avatar
gbazin committed
495
            }
496
497
498
499
500

            break;

        case INPUT_ADD_OPTION:
        {
501
502
503
            const char *psz_option = va_arg( args, const char * );
            const char *psz_value = va_arg( args, const char * );
            char *str;
504
505
            int i;

506
507
            if( asprintf( &str, "%s=%s", psz_option, psz_value ) == -1 )
                return VLC_ENOMEM;
508

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
509
510
            i = input_ItemAddOpt( p_input->p->input.p_item, str,
                                  VLC_INPUT_OPTION_UNIQUE );
511
512
            free( str );
            return i;
513
514
515
516
        }

        case INPUT_GET_BYTE_POSITION:
            pi_64 = (int64_t*)va_arg( args, int64_t * );
zorglub's avatar
zorglub committed
517
518
            *pi_64 = !p_input->p->input.p_stream ? 0 :
                stream_Tell( p_input->p->input.p_stream );
519
520
521
522
            return VLC_SUCCESS;

        case INPUT_SET_BYTE_SIZE:
            pi_64 = (int64_t*)va_arg( args, int64_t * );
zorglub's avatar
zorglub committed
523
524
            *pi_64 = !p_input->p->input.p_stream ? 0 :
                stream_Size( p_input->p->input.p_stream );
525
            return VLC_SUCCESS;
526

527
528
529
530
531
532
533
534
535
536
537
538
        case INPUT_GET_VIDEO_FPS:
        {
            int i;
            pf = (double*)va_arg( args, double * );
            vlc_mutex_lock( &p_input->p->input.p_item->lock );
            *pf = p_input->p->input.f_fps;
            for( i = 0; i < p_input->p->i_slave && *pf <= 0.001; i++ )
                *pf = p_input->p->slave[i]->f_fps;
            vlc_mutex_unlock( &p_input->p->input.p_item->lock );
            return VLC_SUCCESS;
        }

539
540
541
542
543
544
545
546
        case INPUT_ADD_SLAVE:
            psz = (char*)va_arg( args, char * );
            if( psz && *psz )
            {
                val.psz_string = strdup( psz );
                input_ControlPush( p_input, INPUT_CONTROL_ADD_SLAVE, &val );
            }
            return VLC_SUCCESS;
gbazin's avatar
gbazin committed
547

548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
        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;

            vlc_mutex_lock( &p_input->p->input.p_item->lock );
            if( p_input->p->i_attachment <= 0 )
            {
                vlc_mutex_unlock( &p_input->p->input.p_item->lock );
                *ppp_attachment = NULL;
                *pi_attachment = 0;
                return VLC_EGENERIC;
            }
            *pi_attachment = p_input->p->i_attachment;
            *ppp_attachment = malloc( sizeof(input_attachment_t**) * p_input->p->i_attachment );
            for( i = 0; i < p_input->p->i_attachment; i++ )
                (*ppp_attachment)[i] = vlc_input_attachment_Duplicate( p_input->p->attachment[i] );

            vlc_mutex_unlock( &p_input->p->input.p_item->lock );
568
            return VLC_SUCCESS;
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
        }

        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;

            vlc_mutex_lock( &p_input->p->input.p_item->lock );
            for( i = 0; i < p_input->p->i_attachment; i++ )
            {
                if( !strcmp( p_input->p->attachment[i]->psz_name, psz_name ) )
                {
                    *pp_attachment = vlc_input_attachment_Duplicate( p_input->p->attachment[i] );
                    vlc_mutex_unlock( &p_input->p->input.p_item->lock );
                    return VLC_SUCCESS;
                }
            }
            *pp_attachment = NULL;
            vlc_mutex_unlock( &p_input->p->input.p_item->lock );
            return VLC_EGENERIC;
        }


gbazin's avatar
gbazin committed
593
594
        default:
            msg_Err( p_input, "unknown query in input_vaControl" );
Laurent Aimar's avatar
Laurent Aimar committed
595
            return VLC_EGENERIC;
gbazin's avatar
gbazin committed
596
597
    }
}
598

599
600
static void NotifyPlaylist( input_thread_t *p_input )
{
601
602
    playlist_t *p_playlist = pl_Yield( p_input );
    var_SetInteger( p_playlist, "item-change",
zorglub's avatar
zorglub committed
603
                    p_input->p->input.p_item->i_id );
604
    pl_Release( p_input );
605
606
}

607
608
609
610
611
static void UpdateBookmarksOption( input_thread_t *p_input )
{
    int i, i_len = 0;
    char *psz_value = NULL, *psz_next = NULL;

zorglub's avatar
zorglub committed
612
613
    vlc_mutex_lock( &p_input->p->input.p_item->lock );
    for( i = 0; i < p_input->p->i_bookmark; i++ )
614
    {
615
616
617
618
        i_len += snprintf( NULL, 0, "{name=%s,bytes="I64Fd",time="I64Fd"}",
                           p_input->p->bookmark[i]->psz_name,
                           p_input->p->bookmark[i]->i_byte_offset,
                           p_input->p->bookmark[i]->i_time_offset/1000000 );
619
    }
zorglub's avatar
zorglub committed
620
    for( i = 0; i < p_input->p->i_bookmark; i++ )
621
    {
zorglub's avatar
zorglub committed
622
        if( !i ) psz_value = psz_next = malloc( i_len + p_input->p->i_bookmark );
623
624

        sprintf( psz_next, "{name=%s,bytes="I64Fd",time="I64Fd"}",
zorglub's avatar
zorglub committed
625
626
627
                 p_input->p->bookmark[i]->psz_name,
                 p_input->p->bookmark[i]->i_byte_offset,
                 p_input->p->bookmark[i]->i_time_offset/1000000 );
628
629

        psz_next += strlen( psz_next );
zorglub's avatar
zorglub committed
630
        if( i < p_input->p->i_bookmark - 1)
631
632
633
634
        {
            *psz_next = ','; psz_next++;
        }
    }
zorglub's avatar
zorglub committed
635
    vlc_mutex_unlock( &p_input->p->input.p_item->lock );
636

637
638
639
    input_Control( p_input, INPUT_ADD_OPTION, "bookmarks",
                   psz_value ? psz_value : "" );
}