video.c 25.2 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 <math.h>
42
#include <assert.h>
43

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    if( !p_input_thread )
305
        return 0;
306

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

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

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

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

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

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

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

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

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

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

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

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

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

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

429
    for (size_t i = 0; i < n; i++)
430
    {
431
        vout_thread_t *p_vout = pp_vouts[i];
432 433 434 435 436 437 438 439
        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);
440 441
        var_SetString (p_vout, "crop", psz_geometry);
        vlc_object_release (p_vout);
442
    }
443
    free (pp_vouts);
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
444 445
}

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

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

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

459 460 461 462 463 464 465 466 467 468 469
    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 )
470
        == VLC_SUCCESS )
471
    {
472
        var_SetInteger( p_zvbi, "vbi-page", i_page );
473 474 475 476 477
        vlc_object_release( p_zvbi );
    }
    vlc_object_release( p_input_thread );
}

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

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

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

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

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

    if( !p_input_thread )
        return -1;

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

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

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

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

    if( !p_input_thread )
        return -1;

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

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

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

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

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

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

598 599 600 601 602 603 604 605 606 607
        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);
608
}
609

610 611 612 613
/* ************** */
/* module helpers */
/* ************** */

614
static bool find_sub_source_by_name( libvlc_media_player_t *p_mi, const char *restrict name )
615
{
616
    vout_thread_t *vout = GetVout( p_mi, 0 );
617 618
    if (!vout)
        return false;
619

620 621
    char *psz_sources = var_GetString( vout, "sub-source" );
    if( !psz_sources )
622
    {
623 624 625
        libvlc_printerr( "%s not enabled", name );
        vlc_object_release( vout );
        return false;
626
    }
627

628 629 630 631 632
    /* Find 'name'  */
    char *p = strstr( psz_sources, name );
    free( psz_sources );
    vlc_object_release( vout );
    return (p != NULL);
633 634
}

635
typedef const struct {
636
    const char name[20];
637
    unsigned type;
638
} opt_t;
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
        if (vout)
        {
651
            /* Fill sub-source */
652
            vout_EnableFilter( vout, opt->name, value, false );
653
            var_TriggerCallback( vout, "sub-source" );
654 655 656
            vlc_object_release( vout );
        }
        return;
657 658
    }

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

665
    var_SetInteger( p_mi, opt->name, value );
666 667 668
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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


810
/* logo module support */
811

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

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


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


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


856 857 858
/* adjust module support */


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

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
873
    const opt_t *r = option < num_opts ? optlist+option : NULL;
874 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
    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) );
}