video.c 25.3 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
#include <vlc/libvlc_renderer_discoverer.h>
34 35 36 37
#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
38 39 40
#include <vlc_input.h>
#include <vlc_vout.h>

41
#include "media_player_internal.h"
42
#include <math.h>
43
#include <assert.h>
44

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

57 58
    vout_thread_t **pp_vouts;
    if (input_Control( p_input, INPUT_GET_VOUTS, &pp_vouts, n))
59
    {
60 61
        *n = 0;
        pp_vouts = NULL;
62
    }
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
    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
86 87 88 89 90 91 92
    return p_vout;
}

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

93
void libvlc_set_fullscreen( libvlc_media_player_t *p_mi, int b_fullscreen )
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
94
{
95 96
    /* 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
97

98 99 100 101 102 103 104 105 106
    /* 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
107 108
}

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

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

118 119 120 121 122 123
    /* 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
124

125 126 127 128
        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
129 130
}

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

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

141 142 143 144
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
145
{
146 147
    assert( psz_filepath );

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

152 153 154 155 156
    /* 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 );
157
    var_SetInteger( p_vout, "snapshot-width", i_width);
158
    var_Create( p_vout, "snapshot-height", VLC_VAR_INTEGER );
159
    var_SetInteger( p_vout, "snapshot-height", i_height );
160
    var_Create( p_vout, "snapshot-path", VLC_VAR_STRING );
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
161
    var_SetString( p_vout, "snapshot-path", psz_filepath );
162
    var_Create( p_vout, "snapshot-format", VLC_VAR_STRING );
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
163
    var_SetString( p_vout, "snapshot-format", "png" );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
164 165
    var_TriggerCallback( p_vout, "video-snapshot" );
    vlc_object_release( p_vout );
166
    return 0;
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
167 168
}

169 170
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
171
{
172 173
    libvlc_media_track_info_t *info;
    int ret = -1;
Rafaël Carré's avatar
Rafaël Carré committed
174 175
    if (!p_mi->p_md)
        return ret;
176 177 178 179 180 181 182 183 184 185 186 187 188 189
    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;
190
}
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
191

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

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

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

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

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

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

222
unsigned libvlc_media_player_has_vout( libvlc_media_player_t *p_mi )
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
223
{
224 225 226 227 228 229
    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
230 231
}

232
float libvlc_video_get_scale( libvlc_media_player_t *mp )
233
{
234
    float f_scale = var_GetFloat (mp, "zoom");
235
    if (var_GetBool (mp, "autoscale"))
236
        f_scale = 0.f;
237 238 239
    return f_scale;
}

240
void libvlc_video_set_scale( libvlc_media_player_t *p_mp, float f_scale )
241
{
242
    if (isfinite(f_scale) && f_scale != 0.f)
243
        var_SetFloat (p_mp, "zoom", f_scale);
244
    var_SetBool (p_mp, "autoscale", f_scale == 0.f);
245 246 247 248 249 250 251

    /* 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];
252

253
        if (isfinite(f_scale) && f_scale != 0.f)
254
            var_SetFloat (p_vout, "zoom", f_scale);
255
        var_SetBool (p_vout, "autoscale", f_scale == 0.f);
256 257 258
        vlc_object_release (p_vout);
    }
    free (pp_vouts);
259 260
}

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

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

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

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

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

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

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

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

    if( !p_input_thread )
306
        return 0;
307

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

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

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

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

328
    var_Change (p_input_thread, "spu-es", VLC_VAR_GETCHOICES, &list, NULL);
329
    for (int i = 0; i < list.p_list->i_count; i++)
330
    {
331 332 333 334 335 336 337
        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;
        }
338
    }
339
    libvlc_printerr( "Track identifier not found" );
340
end:
341 342 343
    vlc_object_release (p_input_thread);
    var_FreeList (&list, NULL);
    return i_ret;
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
344 345
}

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

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

361 362 363 364 365 366 367
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 )
    {
368
        val = var_GetInteger( p_input_thread, "spu-delay" );
369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386
        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 )
    {
387
        var_SetInteger( p_input_thread, "spu-delay", i_delay );
388 389 390 391 392 393 394 395 396 397 398
        vlc_object_release( p_input_thread );
        ret = 0;
    }
    else
    {
        libvlc_printerr( "No active input" );
    }

    return ret;
}

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

libvlc_track_description_t *
        libvlc_video_get_chapter_description( libvlc_media_player_t *p_mi,
407
                                              int i_title )
408
{
409 410
    char psz_title[sizeof ("title ") + 3 * sizeof (int)];
    sprintf( psz_title,  "title %2u", i_title );
411
    return libvlc_get_track_description( p_mi, psz_title );
412 413
}

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

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

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

427 428
    size_t n;
    vout_thread_t **pp_vouts = GetVouts (p_mi, &n);
429

430
    for (size_t i = 0; i < n; i++)
431
    {
432
        vout_thread_t *p_vout = pp_vouts[i];
433

434 435
        var_SetString (p_vout, "crop", psz_geometry);
        vlc_object_release (p_vout);
436
    }
437
    free (pp_vouts);
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
438 439
}

440 441
int libvlc_video_get_teletext( libvlc_media_player_t *p_mi )
{
442
    return var_GetInteger (p_mi, "vbi-page");
443 444
}

445
void libvlc_video_set_teletext( libvlc_media_player_t *p_mi, int i_page )
446 447 448 449 450
{
    input_thread_t *p_input_thread;
    vlc_object_t *p_zvbi = NULL;
    int telx;

451 452
    var_SetInteger (p_mi, "vbi-page", i_page);

453 454 455 456 457 458 459 460 461 462 463
    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 )
464
        == VLC_SUCCESS )
465
    {
466
        var_SetInteger( p_zvbi, "vbi-page", i_page );
467 468 469 470 471
        vlc_object_release( p_zvbi );
    }
    vlc_object_release( p_input_thread );
}

472
void libvlc_toggle_teletext( libvlc_media_player_t *p_mi )
473
{
474
    input_thread_t *p_input_thread;
475

476
    p_input_thread = libvlc_get_input_thread(p_mi);
477
    if( !p_input_thread ) return;
478

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

497
            var_FreeList( &list, NULL );
498 499 500
        }
    }
    vlc_object_release( p_input_thread );
501 502
}

503
int libvlc_video_get_track_count( libvlc_media_player_t *p_mi )
504
{
505
    input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
506
    int i_track_count;
507 508 509 510

    if( !p_input_thread )
        return -1;

511
    i_track_count = var_CountChoices( p_input_thread, "video-es" );
512

513
    vlc_object_release( p_input_thread );
514
    return i_track_count;
515 516 517
}

libvlc_track_description_t *
518
        libvlc_video_get_track_description( libvlc_media_player_t *p_mi )
519
{
520
    return libvlc_get_track_description( p_mi, "video-es" );
521 522
}

523
int libvlc_video_get_track( libvlc_media_player_t *p_mi )
524
{
525
    input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
526 527 528 529

    if( !p_input_thread )
        return -1;

530
    int id = var_GetInteger( p_input_thread, "video-es" );
531
    vlc_object_release( p_input_thread );
532
    return id;
533 534
}

535
int libvlc_video_set_track( libvlc_media_player_t *p_mi, int i_track )
536
{
537
    input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
538 539 540 541
    vlc_value_t val_list;
    int i_ret = -1;

    if( !p_input_thread )
542
        return -1;
543 544

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

/******************************************************************************
 * libvlc_video_set_deinterlace : enable deinterlace
 *****************************************************************************/
567 568 569 570 571 572
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
573 574 575 576
     && 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
577
     && strcmp (psz_mode, "phosphor") && strcmp (psz_mode, "ivtc"))
578 579
        return;

580
    if (*psz_mode)
581
    {
582 583
        var_SetString (p_mi, "deinterlace-mode", psz_mode);
        var_SetInteger (p_mi, "deinterlace", 1);
584 585
    }
    else
586 587 588 589 590
        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++)
591
    {
592
        vout_thread_t *p_vout = pp_vouts[i];
593

594 595 596 597 598 599 600 601 602 603
        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);
604
}
605

606 607 608 609
/* ************** */
/* module helpers */
/* ************** */

610
static bool find_sub_source_by_name( libvlc_media_player_t *p_mi, const char *restrict name )
611
{
612
    vout_thread_t *vout = GetVout( p_mi, 0 );
613 614
    if (!vout)
        return false;
615

616 617
    char *psz_sources = var_GetString( vout, "sub-source" );
    if( !psz_sources )
618
    {
619 620 621
        libvlc_printerr( "%s not enabled", name );
        vlc_object_release( vout );
        return false;
622
    }
623

624 625 626 627 628
    /* Find 'name'  */
    char *p = strstr( psz_sources, name );
    free( psz_sources );
    vlc_object_release( vout );
    return (p != NULL);
629 630
}

631
typedef const struct {
632
    const char name[20];
633
    unsigned type;
634
} opt_t;
635

636
static void
637 638
set_int( libvlc_media_player_t *p_mi, const char *restrict name,
         const opt_t *restrict opt, int value )
639
{
640 641
    if( !opt ) return;

642
    switch( opt->type )
643
    {
644
        case 0: /* the enabler */
645
        {
646 647 648 649 650 651 652 653
            vout_thread_t *vout = GetVout( p_mi, 0 );
            if (vout != NULL)
            {   /* Fill sub-source */
                vout_EnableFilter( vout, opt->name, value, false );
                var_TriggerCallback( vout, "sub-source" );
                vlc_object_release( vout );
            }
            break;
654
        }
655 656 657 658 659 660 661 662 663
        case VLC_VAR_INTEGER:
            var_SetInteger( p_mi, opt->name, value );
            break;
        case VLC_VAR_FLOAT:
            var_SetFloat( p_mi, opt->name, value );
            break;
        default:
            libvlc_printerr( "Invalid argument to %s in %s", name, "set int" );
            return;
664
    }
665 666 667
}

static int
668 669
get_int( libvlc_media_player_t *p_mi, const char *restrict name,
         const opt_t *restrict opt )
670 671
{
    if( !opt ) return 0;
672

673
    switch( opt->type )
674
    {
675 676
        case 0: /* the enabler */
        {
677 678
            bool b_enabled = find_sub_source_by_name( p_mi, name );
            return b_enabled ? 1 : 0;
679
        }
680
    case VLC_VAR_INTEGER:
681
        return var_GetInteger(p_mi, opt->name);
682 683
    case VLC_VAR_FLOAT:
        return lroundf(var_GetFloat(p_mi, opt->name));
684
    default:
685 686
        libvlc_printerr( "Invalid argument to %s in %s", name, "get int" );
        return 0;
687 688 689
    }
}

690 691 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
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 );
}

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 );
}

720
static void
721 722
set_string( libvlc_media_player_t *p_mi, const char *restrict name,
            const opt_t *restrict opt, const char *restrict psz_value )
723
{
724 725
    if( !opt ) return;

726
    if( opt->type != VLC_VAR_STRING )
727
    {
728 729 730 731 732
        libvlc_printerr( "Invalid argument to %s in %s", name, "set string" );
        return;
    }

    var_SetString( p_mi, opt->name, psz_value );
733
}
734

735
static char *
736 737
get_string( libvlc_media_player_t *p_mi, const char *restrict name,
            const opt_t *restrict opt )
738 739 740
{
    if( !opt ) return NULL;

741
    if( opt->type != VLC_VAR_STRING )
742
    {
743 744
        libvlc_printerr( "Invalid argument to %s in %s", name, "get string" );
        return NULL;
745 746
    }

747 748
    return var_GetString( p_mi, opt->name );
}
749 750

static const opt_t *
751
marq_option_bynumber(unsigned option)
752
{
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
753
    static const opt_t optlist[] =
754 755 756 757 758 759 760 761 762 763 764 765 766
    {
        { "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) };
767

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
768
    const opt_t *r = option < num_opts ? optlist+option : NULL;
769 770 771
    if( !r )
        libvlc_printerr( "Unknown marquee option" );
    return r;
772 773 774
}

/*****************************************************************************
775
 * libvlc_video_get_marquee_int : get a marq option value
776
 *****************************************************************************/
777
int libvlc_video_get_marquee_int( libvlc_media_player_t *p_mi,
778
                                  unsigned option )
779
{
780
    return get_int( p_mi, "marq", marq_option_bynumber(option) );
781
}
782

783 784 785 786
/*****************************************************************************
 * libvlc_video_get_marquee_string : get a marq option value
 *****************************************************************************/
char * libvlc_video_get_marquee_string( libvlc_media_player_t *p_mi,
787
                                        unsigned option )
788
{
789
    return get_string( p_mi, "marq", marq_option_bynumber(option) );
790
}
791

792 793 794 795
/*****************************************************************************
 * libvlc_video_set_marquee_int: enable, disable or set an int option
 *****************************************************************************/
void libvlc_video_set_marquee_int( libvlc_media_player_t *p_mi,
796
                         unsigned option, int value )
797
{
798
    set_int( p_mi, "marq", marq_option_bynumber(option), value );
799
}
800

801 802 803 804
/*****************************************************************************
 * libvlc_video_set_marquee_string: set a string option
 *****************************************************************************/
void libvlc_video_set_marquee_string( libvlc_media_player_t *p_mi,
805
                unsigned option, const char * value )
806
{
807
    set_string( p_mi, "marq", marq_option_bynumber(option), value );
808 809 810
}


811
/* logo module support */
812

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
813
static const opt_t *
814
logo_option_bynumber( unsigned option )
815
{
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
816 817
    static const opt_t vlogo_optlist[] =
    /* depends on libvlc_video_logo_option_t */
818 819 820 821 822 823 824 825 826 827 828 829
    {
        { "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
830
    const opt_t *r = option < num_vlogo_opts ? vlogo_optlist+option : NULL;
831
    if( !r )
832
        libvlc_printerr( "Unknown logo option" );
833 834 835 836
    return r;
}

void libvlc_video_set_logo_string( libvlc_media_player_t *p_mi,
837
                                   unsigned option, const char *psz_value )
838
{
839
    set_string( p_mi,"logo",logo_option_bynumber(option), psz_value );
840 841 842 843
}


void libvlc_video_set_logo_int( libvlc_media_player_t *p_mi,
844
                                unsigned option, int value )
845
{
846
    set_int( p_mi, "logo", logo_option_bynumber(option), value );
847 848 849 850
}


int libvlc_video_get_logo_int( libvlc_media_player_t *p_mi,
851
                               unsigned option )
852
{
853
    return get_int( p_mi, "logo", logo_option_bynumber(option) );
854
}
855 856


857 858 859
/* adjust module support */


Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
860
static const opt_t *
861 862 863 864
adjust_option_bynumber( unsigned option )
{
    static const opt_t optlist[] =
    {
865 866 867
        { "adjust",     0 },
        { "contrast",   VLC_VAR_FLOAT },
        { "brightness", VLC_VAR_FLOAT },
868
        { "hue",        VLC_VAR_FLOAT },
869 870
        { "saturation", VLC_VAR_FLOAT },
        { "gamma",      VLC_VAR_FLOAT },
871 872 873
    };
    enum { num_opts = sizeof(optlist) / sizeof(*optlist) };

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
874
    const opt_t *r = option < num_opts ? optlist+option : NULL;
875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906
    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) );
}