video.c 25.6 KB
Newer Older
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
1 2 3
/*****************************************************************************
 * video.c: libvlc new API video functions
 *****************************************************************************
Jean-Baptiste Kempf's avatar
LGPL  
Jean-Baptiste Kempf committed
4
 * Copyright (C) 2005-2010 VLC authors and VideoLAN
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
5
 *
6
 * $Id$
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
7
 *
8
 * Authors: Clément Stenac <zorglub@videolan.org>
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
9 10 11 12
 *          Filippo Carone <littlejohn@videolan.org>
 *          Jean-Paul Saman <jpsaman _at_ m2x _dot_ nl>
 *          Damien Fouilleul <damienf a_t videolan dot org>
 *
Jean-Baptiste Kempf's avatar
LGPL  
Jean-Baptiste Kempf committed
13 14 15
 * 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
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
16 17 18 19
 * (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
20 21
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
22
 *
Jean-Baptiste Kempf's avatar
LGPL  
Jean-Baptiste Kempf committed
23 24 25
 * 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.
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
26 27
 *****************************************************************************/

28 29 30 31
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
32
#include <vlc/libvlc.h>
33 34 35 36
#include <vlc/libvlc_media.h>
#include <vlc/libvlc_media_player.h>

#include <vlc_common.h>
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
37 38 39
#include <vlc_input.h>
#include <vlc_vout.h>

40
#include "media_player_internal.h"
41
#include <assert.h>
42

Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
43
/*
44
 * Remember to release the returned vout_thread_t.
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
45
 */
46
static vout_thread_t **GetVouts( libvlc_media_player_t *p_mi, size_t *n )
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
47
{
48
    input_thread_t *p_input = libvlc_get_input_thread( p_mi );
49
    if( !p_input )
50 51
    {
        *n = 0;
52
        return NULL;
53
    }
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
54

55 56
    vout_thread_t **pp_vouts;
    if (input_Control( p_input, INPUT_GET_VOUTS, &pp_vouts, n))
57
    {
58 59
        *n = 0;
        pp_vouts = NULL;
60
    }
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
    vlc_object_release (p_input);
    return pp_vouts;
}

static vout_thread_t *GetVout (libvlc_media_player_t *mp, size_t num)
{
    vout_thread_t *p_vout = NULL;
    size_t n;
    vout_thread_t **pp_vouts = GetVouts (mp, &n);
    if (pp_vouts == NULL)
        goto err;

    if (num < n)
        p_vout = pp_vouts[num];

    for (size_t i = 0; i < n; i++)
        if (i != num)
            vlc_object_release (pp_vouts[i]);
    free (pp_vouts);

    if (p_vout == NULL)
err:
        libvlc_printerr ("Video output not active");
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
84 85 86 87 88 89 90
    return p_vout;
}

/**********************************************************************
 * Exported functions
 **********************************************************************/

91
void libvlc_set_fullscreen( libvlc_media_player_t *p_mi, int b_fullscreen )
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
92
{
93 94
    /* This will work even if the video is not currently active */
    var_SetBool (p_mi, "fullscreen", !!b_fullscreen);
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
95

96 97 98 99 100 101 102 103 104
    /* Apply to current video outputs (if any) */
    size_t n;
    vout_thread_t **pp_vouts = GetVouts (p_mi, &n);
    for (size_t i = 0; i < n; i++)
    {
        var_SetBool (pp_vouts[i], "fullscreen", b_fullscreen);
        vlc_object_release (pp_vouts[i]);
    }
    free (pp_vouts);
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
105 106
}

107
int libvlc_get_fullscreen( libvlc_media_player_t *p_mi )
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
108
{
109
    return var_GetBool (p_mi, "fullscreen");
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
110 111
}

112
void libvlc_toggle_fullscreen( libvlc_media_player_t *p_mi )
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
113
{
114
    bool b_fullscreen = var_ToggleBool (p_mi, "fullscreen");
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
115

116 117 118 119 120 121
    /* Apply to current video outputs (if any) */
    size_t n;
    vout_thread_t **pp_vouts = GetVouts (p_mi, &n);
    for (size_t i = 0; i < n; i++)
    {
        vout_thread_t *p_vout = pp_vouts[i];
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
122

123 124 125 126
        var_SetBool (p_vout, "fullscreen", b_fullscreen);
        vlc_object_release (p_vout);
    }
    free (pp_vouts);
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
127 128
}

129 130
void libvlc_video_set_key_input( libvlc_media_player_t *p_mi, unsigned on )
{
131
    var_SetBool (p_mi, "keyboard-events", !!on);
132 133 134 135
}

void libvlc_video_set_mouse_input( libvlc_media_player_t *p_mi, unsigned on )
{
136
    var_SetBool (p_mi, "mouse-events", !!on);
137 138
}

139 140 141 142
int
libvlc_video_take_snapshot( libvlc_media_player_t *p_mi, unsigned num,
                            const char *psz_filepath,
                            unsigned int i_width, unsigned int i_height )
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
143
{
144 145
    assert( psz_filepath );

146 147 148
    vout_thread_t *p_vout = GetVout (p_mi, num);
    if (p_vout == NULL)
        return -1;
149

150 151 152 153 154
    /* FIXME: This is not atomic. All parameters should be passed at once
     * (obviously _not_ with var_*()). Also, the libvlc object should not be
     * used for the callbacks: that breaks badly if there are concurrent
     * media players in the instance. */
    var_Create( p_vout, "snapshot-width", VLC_VAR_INTEGER );
155
    var_SetInteger( p_vout, "snapshot-width", i_width);
156
    var_Create( p_vout, "snapshot-height", VLC_VAR_INTEGER );
157
    var_SetInteger( p_vout, "snapshot-height", i_height );
158
    var_Create( p_vout, "snapshot-path", VLC_VAR_STRING );
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
159
    var_SetString( p_vout, "snapshot-path", psz_filepath );
160
    var_Create( p_vout, "snapshot-format", VLC_VAR_STRING );
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
161
    var_SetString( p_vout, "snapshot-format", "png" );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
162 163
    var_TriggerCallback( p_vout, "video-snapshot" );
    vlc_object_release( p_vout );
164
    return 0;
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
165 166
}

167 168
int libvlc_video_get_size( libvlc_media_player_t *p_mi, unsigned num,
                           unsigned *restrict px, unsigned *restrict py )
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
169
{
170 171
    libvlc_media_track_info_t *info;
    int ret = -1;
Rafaël Carré's avatar
Rafaël Carré committed
172 173
    if (!p_mi->p_md)
        return ret;
174 175 176 177 178 179 180 181 182 183 184 185 186 187
    int infos = libvlc_media_get_tracks_info(p_mi->p_md, &info);
    if (infos <= 0)
        return ret;

    for (int i = 0; i < infos; i++)
        if (info[i].i_type == libvlc_track_video && num-- == 0) {
            *px = info[i].u.video.i_width;
            *py = info[i].u.video.i_height;
            ret = 0;
            break;
        }

    free(info);
    return ret;
188
}
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
189

190 191
int libvlc_video_get_height( libvlc_media_player_t *p_mi )
{
192
    unsigned width, height;
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
193

194
    if (libvlc_video_get_size (p_mi, 0, &width, &height))
195
        return 0;
196
    return height;
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
197 198
}

199
int libvlc_video_get_width( libvlc_media_player_t *p_mi )
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
200
{
201
    unsigned width, height;
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
202

203
    if (libvlc_video_get_size (p_mi, 0, &width, &height))
204
        return 0;
205
    return width;
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
206 207
}

208
int libvlc_video_get_cursor( libvlc_media_player_t *mp, unsigned num,
209
                             int *restrict px, int *restrict py )
210 211 212 213 214
{
    vout_thread_t *p_vout = GetVout (mp, num);
    if (p_vout == NULL)
        return -1;

215
    var_GetCoords (p_vout, "mouse-moved", px, py);
216 217 218 219
    vlc_object_release (p_vout);
    return 0;
}

220
unsigned libvlc_media_player_has_vout( libvlc_media_player_t *p_mi )
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
221
{
222 223 224 225 226 227
    size_t n;
    vout_thread_t **pp_vouts = GetVouts (p_mi, &n);
    for (size_t i = 0; i < n; i++)
        vlc_object_release (pp_vouts[i]);
    free (pp_vouts);
    return n;
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
228 229
}

230
float libvlc_video_get_scale( libvlc_media_player_t *mp )
231
{
232 233
    float f_scale = var_GetFloat (mp, "scale");
    if (var_GetBool (mp, "autoscale"))
234 235 236 237
        f_scale = 0.;
    return f_scale;
}

238
void libvlc_video_set_scale( libvlc_media_player_t *p_mp, float f_scale )
239
{
240 241
    if (f_scale != 0.)
        var_SetFloat (p_mp, "scale", f_scale);
242
    var_SetBool (p_mp, "autoscale", f_scale == 0.);
243 244 245 246 247 248 249

    /* Apply to current video outputs (if any) */
    size_t n;
    vout_thread_t **pp_vouts = GetVouts (p_mp, &n);
    for (size_t i = 0; i < n; i++)
    {
        vout_thread_t *p_vout = pp_vouts[i];
250

251 252
        if (f_scale != 0.)
            var_SetFloat (p_vout, "scale", f_scale);
253
        var_SetBool (p_vout, "autoscale", f_scale == 0.);
254 255 256
        vlc_object_release (p_vout);
    }
    free (pp_vouts);
257 258
}

259
char *libvlc_video_get_aspect_ratio( libvlc_media_player_t *p_mi )
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
260
{
261
    return var_GetNonEmptyString (p_mi, "aspect-ratio");
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
262 263
}

264
void libvlc_video_set_aspect_ratio( libvlc_media_player_t *p_mi,
265
                                    const char *psz_aspect )
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
266
{
267 268 269
    if (psz_aspect == NULL)
        psz_aspect = "";
    var_SetString (p_mi, "aspect-ratio", psz_aspect);
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
270

271 272 273
    size_t n;
    vout_thread_t **pp_vouts = GetVouts (p_mi, &n);
    for (size_t i = 0; i < n; i++)
274
    {
275 276 277 278
        vout_thread_t *p_vout = pp_vouts[i];

        var_SetString (p_vout, "aspect-ratio", psz_aspect);
        vlc_object_release (p_vout);
279
    }
280
    free (pp_vouts);
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
281 282
}

283
int libvlc_video_get_spu( libvlc_media_player_t *p_mi )
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
284
{
285
    input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
286

287 288 289 290 291
    if( !p_input_thread )
    {
        libvlc_printerr( "No active input" );
        return -1;
    }
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
292

293
    int i_spu = var_GetInteger( p_input_thread, "spu-es" );
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
294 295 296 297
    vlc_object_release( p_input_thread );
    return i_spu;
}

298
int libvlc_video_get_spu_count( libvlc_media_player_t *p_mi )
299
{
300
    input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
301
    int i_spu_count;
302 303

    if( !p_input_thread )
304
        return 0;
305

306
    i_spu_count = var_CountChoices( p_input_thread, "spu-es" );
307
    vlc_object_release( p_input_thread );
308
    return i_spu_count;
309 310 311
}

libvlc_track_description_t *
312
        libvlc_video_get_spu_description( libvlc_media_player_t *p_mi )
313
{
314
    return libvlc_get_track_description( p_mi, "spu-es" );
315 316
}

317
int libvlc_video_set_spu( libvlc_media_player_t *p_mi, unsigned i_spu )
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
318
{
319
    input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
320
    vlc_value_t list;
321
    int i_ret = -1;
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
322

323
    if( !p_input_thread )
324
        return -1;
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
325

326
    var_Change (p_input_thread, "spu-es", VLC_VAR_GETCHOICES, &list, NULL);
327
    for (int i = 0; i < list.p_list->i_count; i++)
328
    {
329 330 331 332 333 334 335
        if( i_spu == list.p_list->p_values[i].i_int )
        {
            if( var_SetInteger( p_input_thread, "spu-es", i_spu ) < 0 )
                break;
            i_ret = 0;
            goto end;
        }
336
    }
337
    libvlc_printerr( "Track identifier not found" );
338
end:
339 340 341
    vlc_object_release (p_input_thread);
    var_FreeList (&list, NULL);
    return i_ret;
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
342 343
}

344
int libvlc_video_set_subtitle_file( libvlc_media_player_t *p_mi,
345
                                    const char *psz_subtitle )
346
{
347
    input_thread_t *p_input_thread = libvlc_get_input_thread ( p_mi );
348 349 350 351
    bool b_ret = false;

    if( p_input_thread )
    {
352
        if( !input_AddSubtitle( p_input_thread, psz_subtitle, true ) )
353 354 355 356 357 358
            b_ret = true;
        vlc_object_release( p_input_thread );
    }
    return b_ret;
}

359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396
int64_t libvlc_video_get_spu_delay( libvlc_media_player_t *p_mi )
{
    input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
    int64_t val = 0;

    if( p_input_thread )
    {
        val = var_GetTime( p_input_thread, "spu-delay" );
        vlc_object_release( p_input_thread );
    }
    else
    {
        libvlc_printerr( "No active input" );
    }

    return val;
}

int libvlc_video_set_spu_delay( libvlc_media_player_t *p_mi,
                                int64_t i_delay )
{
    input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
    int ret = -1;

    if( p_input_thread )
    {
        var_SetTime( p_input_thread, "spu-delay", i_delay );
        vlc_object_release( p_input_thread );
        ret = 0;
    }
    else
    {
        libvlc_printerr( "No active input" );
    }

    return ret;
}

397
libvlc_track_description_t *
398
        libvlc_video_get_title_description( libvlc_media_player_t *p_mi )
399
{
400
    return libvlc_get_track_description( p_mi, "title" );
401 402 403 404
}

libvlc_track_description_t *
        libvlc_video_get_chapter_description( libvlc_media_player_t *p_mi,
405
                                              int i_title )
406 407 408
{
    char psz_title[12];
    sprintf( psz_title,  "title %2i", i_title );
409
    return libvlc_get_track_description( p_mi, psz_title );
410 411
}

412
char *libvlc_video_get_crop_geometry (libvlc_media_player_t *p_mi)
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
413
{
414
    return var_GetNonEmptyString (p_mi, "crop");
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
415 416
}

417
void libvlc_video_set_crop_geometry( libvlc_media_player_t *p_mi,
418
                                     const char *psz_geometry )
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
419
{
420 421
    if (psz_geometry == NULL)
        psz_geometry = "";
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
422

423
    var_SetString (p_mi, "crop", psz_geometry);
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
424

425 426
    size_t n;
    vout_thread_t **pp_vouts = GetVouts (p_mi, &n);
427

428
    for (size_t i = 0; i < n; i++)
429
    {
430
        vout_thread_t *p_vout = pp_vouts[i];
431 432 433 434 435 436 437 438
        vlc_value_t val;

        /* Make sure the geometry is in the choice list */
        /* Earlier choices are removed to not grow a long list over time. */
        /* FIXME: not atomic - lock? */
        val.psz_string = (char *)psz_geometry;
        var_Change (p_vout, "crop", VLC_VAR_CLEARCHOICES, NULL, NULL);
        var_Change (p_vout, "crop", VLC_VAR_ADDCHOICE, &val, &val);
439 440
        var_SetString (p_vout, "crop", psz_geometry);
        vlc_object_release (p_vout);
441
    }
442
    free (pp_vouts);
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
443 444
}

445 446
int libvlc_video_get_teletext( libvlc_media_player_t *p_mi )
{
447
    return var_GetInteger (p_mi, "vbi-page");
448 449
}

450
void libvlc_video_set_teletext( libvlc_media_player_t *p_mi, int i_page )
451 452 453 454 455
{
    input_thread_t *p_input_thread;
    vlc_object_t *p_zvbi = NULL;
    int telx;

456 457
    var_SetInteger (p_mi, "vbi-page", i_page);

458 459 460 461 462 463 464 465 466 467 468
    p_input_thread = libvlc_get_input_thread( p_mi );
    if( !p_input_thread ) return;

    if( var_CountChoices( p_input_thread, "teletext-es" ) <= 0 )
    {
        vlc_object_release( p_input_thread );
        return;
    }

    telx = var_GetInteger( p_input_thread, "teletext-es" );
    if( input_GetEsObjects( p_input_thread, telx, &p_zvbi, NULL, NULL )
469
        == VLC_SUCCESS )
470
    {
471
        var_SetInteger( p_zvbi, "vbi-page", i_page );
472 473 474 475 476
        vlc_object_release( p_zvbi );
    }
    vlc_object_release( p_input_thread );
}

477
void libvlc_toggle_teletext( libvlc_media_player_t *p_mi )
478
{
479
    input_thread_t *p_input_thread;
480

481
    p_input_thread = libvlc_get_input_thread(p_mi);
482
    if( !p_input_thread ) return;
483

484
    if( var_CountChoices( p_input_thread, "teletext-es" ) <= 0 )
485
    {
486 487 488 489
        vlc_object_release( p_input_thread );
        return;
    }
    const bool b_selected = var_GetInteger( p_input_thread, "teletext-es" ) >= 0;
490
    if( b_selected )
491 492 493
    {
        var_SetInteger( p_input_thread, "spu-es", -1 );
    }
494 495
    else
    {
496 497
        vlc_value_t list;
        if( !var_Change( p_input_thread, "teletext-es", VLC_VAR_GETLIST, &list, NULL ) )
498
        {
499 500
            if( list.p_list->i_count > 0 )
                var_SetInteger( p_input_thread, "spu-es", list.p_list->p_values[0].i_int );
501

502
            var_FreeList( &list, NULL );
503 504 505
        }
    }
    vlc_object_release( p_input_thread );
506 507
}

508
int libvlc_video_get_track_count( libvlc_media_player_t *p_mi )
509
{
510
    input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
511
    int i_track_count;
512 513 514 515

    if( !p_input_thread )
        return -1;

516
    i_track_count = var_CountChoices( p_input_thread, "video-es" );
517

518
    vlc_object_release( p_input_thread );
519
    return i_track_count;
520 521 522
}

libvlc_track_description_t *
523
        libvlc_video_get_track_description( libvlc_media_player_t *p_mi )
524
{
525
    return libvlc_get_track_description( p_mi, "video-es" );
526 527
}

528
int libvlc_video_get_track( libvlc_media_player_t *p_mi )
529
{
530
    input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
531 532 533 534

    if( !p_input_thread )
        return -1;

535
    int id = var_GetInteger( p_input_thread, "video-es" );
536
    vlc_object_release( p_input_thread );
537
    return id;
538 539
}

540
int libvlc_video_set_track( libvlc_media_player_t *p_mi, int i_track )
541
{
542
    input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
543 544 545 546
    vlc_value_t val_list;
    int i_ret = -1;

    if( !p_input_thread )
547
        return -1;
548 549

    var_Change( p_input_thread, "video-es", VLC_VAR_GETCHOICES, &val_list, NULL );
550
    for( int i = 0; i < val_list.p_list->i_count; i++ )
551
    {
552
        if( i_track == val_list.p_list->p_values[i].i_int )
553
        {
554
            if( var_SetInteger( p_input_thread, "video-es", i_track ) < 0 )
555
                break;
556
            i_ret = 0;
557
            goto end;
558 559
        }
    }
560
    libvlc_printerr( "Track identifier not found" );
561
end:
562
    var_FreeList( &val_list, NULL );
563
    vlc_object_release( p_input_thread );
564
    return i_ret;
565
}
566 567 568 569

/******************************************************************************
 * libvlc_video_set_deinterlace : enable deinterlace
 *****************************************************************************/
570 571 572 573 574 575
void libvlc_video_set_deinterlace( libvlc_media_player_t *p_mi,
                                   const char *psz_mode )
{
    if (psz_mode == NULL)
        psz_mode = "";
    if (*psz_mode
Juha Jeronen's avatar
Juha Jeronen committed
576 577 578 579
     && strcmp (psz_mode, "blend")    && strcmp (psz_mode, "bob")
     && strcmp (psz_mode, "discard")  && strcmp (psz_mode, "linear")
     && strcmp (psz_mode, "mean")     && strcmp (psz_mode, "x")
     && strcmp (psz_mode, "yadif")    && strcmp (psz_mode, "yadif2x")
Juha Jeronen's avatar
Juha Jeronen committed
580
     && strcmp (psz_mode, "phosphor") && strcmp (psz_mode, "ivtc"))
581 582
        return;

583
    if (*psz_mode)
584
    {
585 586
        var_SetString (p_mi, "deinterlace-mode", psz_mode);
        var_SetInteger (p_mi, "deinterlace", 1);
587 588
    }
    else
589 590 591 592 593
        var_SetInteger (p_mi, "deinterlace", 0);

    size_t n;
    vout_thread_t **pp_vouts = GetVouts (p_mi, &n);
    for (size_t i = 0; i < n; i++)
594
    {
595
        vout_thread_t *p_vout = pp_vouts[i];
596

597 598 599 600 601 602 603 604 605 606
        if (*psz_mode)
        {
            var_SetString (p_vout, "deinterlace-mode", psz_mode);
            var_SetInteger (p_vout, "deinterlace", 1);
        }
        else
            var_SetInteger (p_vout, "deinterlace", 0);
        vlc_object_release (p_vout);
    }
    free (pp_vouts);
607
}
608

609 610 611 612
/* ************** */
/* module helpers */
/* ************** */

613

614
static vlc_object_t *get_object( libvlc_media_player_t * p_mi,
615
                                 const char *name )
616
{
617 618 619
    vlc_object_t *object;
    vout_thread_t *vout = GetVout( p_mi, 0 );

620
    if( vout )
621
    {
622
        object = vlc_object_find_name( vout, name );
623 624
        vlc_object_release(vout);
    }
625 626 627
    else
        object = NULL;

628 629 630
    if( !object )
        libvlc_printerr( "%s not enabled", name );
    return object;
631 632 633
}


634
typedef const struct {
635
    const char name[20];
636
    unsigned type;
637
} opt_t;
638

639 640

static void
641 642
set_int( libvlc_media_player_t *p_mi, const char *restrict name,
         const opt_t *restrict opt, int value )
643
{
644 645 646
    if( !opt ) return;

    if( !opt->type ) /* the enabler */
647
    {
648
        vout_thread_t *vout = GetVout( p_mi, 0 );
649 650 651 652 653 654
        if (vout)
        {
            vout_EnableFilter( vout, opt->name, value, false );
            vlc_object_release( vout );
        }
        return;
655 656
    }

657 658 659 660 661
    if( opt->type != VLC_VAR_INTEGER )
    {
        libvlc_printerr( "Invalid argument to %s in %s", name, "set int" );
        return;
    }
662

663 664 665
    var_SetInteger(p_mi, opt->name, value);
    vlc_object_t *object = get_object( p_mi, name );
    if( object )
666
    {
667
        var_SetInteger(object, opt->name, value);
668
        vlc_object_release( object );
669
    }
670 671 672 673
}


static int
674 675
get_int( libvlc_media_player_t *p_mi, const char *restrict name,
         const opt_t *restrict opt )
676 677
{
    if( !opt ) return 0;
678

679
    switch( opt->type )
680
    {
681 682 683 684 685 686
        case 0: /* the enabler */
        {
            vlc_object_t *object = get_object( p_mi, name );
            vlc_object_release( object );
            return object != NULL;
        }
687
    case VLC_VAR_INTEGER:
688
        return var_GetInteger(p_mi, opt->name);
689
    default:
690 691
        libvlc_printerr( "Invalid argument to %s in %s", name, "get int" );
        return 0;
692 693 694
    }
}

695

696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735
static void
set_float( libvlc_media_player_t *p_mi, const char *restrict name,
            const opt_t *restrict opt, float value )
{
    if( !opt ) return;

    if( opt->type != VLC_VAR_FLOAT )
    {
        libvlc_printerr( "Invalid argument to %s in %s", name, "set float" );
        return;
    }

    var_SetFloat( p_mi, opt->name, value );

    vlc_object_t *object = get_object( p_mi, name );
    if( object )
    {
        var_SetFloat(object, opt->name, value );
        vlc_object_release( object );
    }
}


static float
get_float( libvlc_media_player_t *p_mi, const char *restrict name,
            const opt_t *restrict opt )
{
    if( !opt ) return 0.0;


    if( opt->type != VLC_VAR_FLOAT )
    {
        libvlc_printerr( "Invalid argument to %s in %s", name, "get float" );
        return 0.0;
    }

    return var_GetFloat( p_mi, opt->name );
}


736
static void
737 738
set_string( libvlc_media_player_t *p_mi, const char *restrict name,
            const opt_t *restrict opt, const char *restrict psz_value )
739
{
740 741
    if( !opt ) return;

742
    if( opt->type != VLC_VAR_STRING )
743
    {
744 745 746 747 748 749 750 751 752 753 754
        libvlc_printerr( "Invalid argument to %s in %s", name, "set string" );
        return;
    }

    var_SetString( p_mi, opt->name, psz_value );

    vlc_object_t *object = get_object( p_mi, name );
    if( object )
    {
        var_SetString(object, opt->name, psz_value );
        vlc_object_release( object );
755
    }
756
}
757

758 759

static char *
760 761
get_string( libvlc_media_player_t *p_mi, const char *restrict name,
            const opt_t *restrict opt )
762 763 764
{
    if( !opt ) return NULL;

765
    if( opt->type != VLC_VAR_STRING )
766
    {
767 768
        libvlc_printerr( "Invalid argument to %s in %s", name, "get string" );
        return NULL;
769 770
    }

771 772
    return var_GetString( p_mi, opt->name );
}
773

774

775
static const opt_t *
776
marq_option_bynumber(unsigned option)
777
{
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
778
    static const opt_t optlist[] =
779 780 781 782 783 784 785 786 787 788 789 790 791
    {
        { "marq",          0 },
        { "marq-marquee",  VLC_VAR_STRING },
        { "marq-color",    VLC_VAR_INTEGER },
        { "marq-opacity",  VLC_VAR_INTEGER },
        { "marq-position", VLC_VAR_INTEGER },
        { "marq-refresh",  VLC_VAR_INTEGER },
        { "marq-size",     VLC_VAR_INTEGER },
        { "marq-timeout",  VLC_VAR_INTEGER },
        { "marq-x",        VLC_VAR_INTEGER },
        { "marq-y",        VLC_VAR_INTEGER },
    };
    enum { num_opts = sizeof(optlist) / sizeof(*optlist) };
792

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
793
    const opt_t *r = option < num_opts ? optlist+option : NULL;
794 795 796
    if( !r )
        libvlc_printerr( "Unknown marquee option" );
    return r;
797 798
}

799
static vlc_object_t *get_object( libvlc_media_player_t *, const char *);
800

801
/*****************************************************************************
802
 * libvlc_video_get_marquee_int : get a marq option value
803
 *****************************************************************************/
804
int libvlc_video_get_marquee_int( libvlc_media_player_t *p_mi,
805
                                  unsigned option )
806
{
807
    return get_int( p_mi, "marq", marq_option_bynumber(option) );
808
}
809

810 811 812 813
/*****************************************************************************
 * libvlc_video_get_marquee_string : get a marq option value
 *****************************************************************************/
char * libvlc_video_get_marquee_string( libvlc_media_player_t *p_mi,
814
                                        unsigned option )
815
{
816
    return get_string( p_mi, "marq", marq_option_bynumber(option) );
817
}
818

819 820 821 822
/*****************************************************************************
 * libvlc_video_set_marquee_int: enable, disable or set an int option
 *****************************************************************************/
void libvlc_video_set_marquee_int( libvlc_media_player_t *p_mi,
823
                         unsigned option, int value )
824
{
825
    set_int( p_mi, "marq", marq_option_bynumber(option), value );
826
}
827

828 829 830 831
/*****************************************************************************
 * libvlc_video_set_marquee_string: set a string option
 *****************************************************************************/
void libvlc_video_set_marquee_string( libvlc_media_player_t *p_mi,
832
                unsigned option, const char * value )
833
{
834
    set_string( p_mi, "marq", marq_option_bynumber(option), value );
835 836 837
}


838
/* logo module support */
839 840


Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
841
static const opt_t *
842
logo_option_bynumber( unsigned option )
843
{
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
844 845
    static const opt_t vlogo_optlist[] =
    /* depends on libvlc_video_logo_option_t */
846 847 848 849 850 851 852 853 854 855 856 857
    {
        { "logo",          0 },
        { "logo-file",     VLC_VAR_STRING },
        { "logo-x",        VLC_VAR_INTEGER },
        { "logo-y",        VLC_VAR_INTEGER },
        { "logo-delay",    VLC_VAR_INTEGER },
        { "logo-repeat",   VLC_VAR_INTEGER },
        { "logo-opacity",  VLC_VAR_INTEGER },
        { "logo-position", VLC_VAR_INTEGER },
    };
    enum { num_vlogo_opts = sizeof(vlogo_optlist) / sizeof(*vlogo_optlist) };

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
858
    const opt_t *r = option < num_vlogo_opts ? vlogo_optlist+option : NULL;
859
    if( !r )
860
        libvlc_printerr( "Unknown logo option" );
861 862 863 864 865
    return r;
}


void libvlc_video_set_logo_string( libvlc_media_player_t *p_mi,
866
                                   unsigned option, const char *psz_value )
867
{
868
    set_string( p_mi,"logo",logo_option_bynumber(option),psz_value );
869 870 871 872
}


void libvlc_video_set_logo_int( libvlc_media_player_t *p_mi,
873
                                unsigned option, int value )
874
{
875
    set_int( p_mi, "logo", logo_option_bynumber(option), value );
876 877 878 879
}


int libvlc_video_get_logo_int( libvlc_media_player_t *p_mi,
880
                               unsigned option )
881
{
882
    return get_int( p_mi, "logo", logo_option_bynumber(option) );
883
}
884 885


886 887 888
/* adjust module support */


Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
889
static const opt_t *
890 891 892 893 894 895 896 897 898 899 900 901 902
adjust_option_bynumber( unsigned option )
{
    static const opt_t optlist[] =
    {
        { "adjust",               0 },
        { "contrast",             VLC_VAR_FLOAT },
        { "brightness",           VLC_VAR_FLOAT },
        { "hue",                  VLC_VAR_INTEGER },
        { "saturation",           VLC_VAR_FLOAT },
        { "gamma",                VLC_VAR_FLOAT },
    };
    enum { num_opts = sizeof(optlist) / sizeof(*optlist) };

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
903
    const opt_t *r = option < num_opts ? optlist+option : NULL;
904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935
    if( !r )
        libvlc_printerr( "Unknown adjust option" );
    return r;
}


void libvlc_video_set_adjust_int( libvlc_media_player_t *p_mi,
                                  unsigned option, int value )
{
    set_int( p_mi, "adjust", adjust_option_bynumber(option), value );
}


int libvlc_video_get_adjust_int( libvlc_media_player_t *p_mi,
                                 unsigned option )
{
    return get_int( p_mi, "adjust", adjust_option_bynumber(option) );
}


void libvlc_video_set_adjust_float( libvlc_media_player_t *p_mi,
                                    unsigned option, float value )
{
    set_float( p_mi, "adjust", adjust_option_bynumber(option), value );
}


float libvlc_video_get_adjust_float( libvlc_media_player_t *p_mi,
                                     unsigned option )
{
    return get_float( p_mi, "adjust", adjust_option_bynumber(option) );
}