video.c 26.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 <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
    vlc_value_t val_list;
    vlc_value_t val;
    int i_spu = -1;
    int i_ret = -1;
    int i;

292 293 294 295 296
    if( !p_input_thread )
    {
        libvlc_printerr( "No active input" );
        return -1;
    }
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
297 298 299 300 301

    i_ret = var_Get( p_input_thread, "spu-es", &val );
    if( i_ret < 0 )
    {
        vlc_object_release( p_input_thread );
302
        libvlc_printerr( "Subtitle information not found" );
303
        return -1;
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
304 305 306 307 308
    }

    var_Change( p_input_thread, "spu-es", VLC_VAR_GETCHOICES, &val_list, NULL );
    for( i = 0; i < val_list.p_list->i_count; i++ )
    {
309
        if( val.i_int == val_list.p_list->p_values[i].i_int )
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
310 311 312 313 314
        {
            i_spu = i;
            break;
        }
    }
315
    var_FreeList( &val_list, NULL );
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
316 317 318 319
    vlc_object_release( p_input_thread );
    return i_spu;
}

320
int libvlc_video_get_spu_count( libvlc_media_player_t *p_mi )
321
{
322
    input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
323
    int i_spu_count;
324 325

    if( !p_input_thread )
326
        return 0;
327

328
    i_spu_count = var_CountChoices( p_input_thread, "spu-es" );
329
    vlc_object_release( p_input_thread );
330
    return i_spu_count;
331 332 333
}

libvlc_track_description_t *
334
        libvlc_video_get_spu_description( libvlc_media_player_t *p_mi )
335
{
336
    return libvlc_get_track_description( p_mi, "spu-es" );
337 338
}

339
int libvlc_video_set_spu( libvlc_media_player_t *p_mi, unsigned i_spu )
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
340
{
341
    input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
342 343
    vlc_value_t list;
    int i_ret = 0;
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
344

345
    if( !p_input_thread )
346
        return -1;
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
347

348
    var_Change (p_input_thread, "spu-es", VLC_VAR_GETCHOICES, &list, NULL);
349

350
    if (i_spu > (unsigned)list.p_list->i_count)
351
    {
352 353 354
        libvlc_printerr( "Subtitle number out of range (%u/%u)",
                         i_spu, list.p_list->i_count );
        i_ret = -1;
355
        goto end;
356
    }
357 358
    var_SetInteger (p_input_thread, "spu-es",
                    list.p_list->p_values[i_spu].i_int);
359
end:
360 361 362
    vlc_object_release (p_input_thread);
    var_FreeList (&list, NULL);
    return i_ret;
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
363 364
}

365
int libvlc_video_set_subtitle_file( libvlc_media_player_t *p_mi,
366
                                    const char *psz_subtitle )
367
{
368
    input_thread_t *p_input_thread = libvlc_get_input_thread ( p_mi );
369 370 371 372
    bool b_ret = false;

    if( p_input_thread )
    {
373
        if( !input_AddSubtitle( p_input_thread, psz_subtitle, true ) )
374 375 376 377 378 379
            b_ret = true;
        vlc_object_release( p_input_thread );
    }
    return b_ret;
}

380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417
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;
}

418
libvlc_track_description_t *
419
        libvlc_video_get_title_description( libvlc_media_player_t *p_mi )
420
{
421
    return libvlc_get_track_description( p_mi, "title" );
422 423 424 425
}

libvlc_track_description_t *
        libvlc_video_get_chapter_description( libvlc_media_player_t *p_mi,
426
                                              int i_title )
427 428 429
{
    char psz_title[12];
    sprintf( psz_title,  "title %2i", i_title );
430
    return libvlc_get_track_description( p_mi, psz_title );
431 432
}

433
char *libvlc_video_get_crop_geometry (libvlc_media_player_t *p_mi)
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
434
{
435
    return var_GetNonEmptyString (p_mi, "crop");
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
436 437
}

438
void libvlc_video_set_crop_geometry( libvlc_media_player_t *p_mi,
439
                                     const char *psz_geometry )
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
440
{
441 442
    if (psz_geometry == NULL)
        psz_geometry = "";
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
443

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

446 447
    size_t n;
    vout_thread_t **pp_vouts = GetVouts (p_mi, &n);
448

449
    for (size_t i = 0; i < n; i++)
450
    {
451
        vout_thread_t *p_vout = pp_vouts[i];
452 453 454 455 456 457 458 459
        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);
460 461
        var_SetString (p_vout, "crop", psz_geometry);
        vlc_object_release (p_vout);
462
    }
463
    free (pp_vouts);
Pierre d'Herbemont's avatar
Oops.  
Pierre d'Herbemont committed
464 465
}

466 467
int libvlc_video_get_teletext( libvlc_media_player_t *p_mi )
{
468
    return var_GetInteger (p_mi, "vbi-page");
469 470
}

471
void libvlc_video_set_teletext( libvlc_media_player_t *p_mi, int i_page )
472 473 474 475 476
{
    input_thread_t *p_input_thread;
    vlc_object_t *p_zvbi = NULL;
    int telx;

477 478
    var_SetInteger (p_mi, "vbi-page", i_page);

479 480 481 482 483 484 485 486 487 488 489
    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 )
490
        == VLC_SUCCESS )
491
    {
492
        var_SetInteger( p_zvbi, "vbi-page", i_page );
493 494 495 496 497
        vlc_object_release( p_zvbi );
    }
    vlc_object_release( p_input_thread );
}

498
void libvlc_toggle_teletext( libvlc_media_player_t *p_mi )
499
{
500
    input_thread_t *p_input_thread;
501

502
    p_input_thread = libvlc_get_input_thread(p_mi);
503
    if( !p_input_thread ) return;
504

505
    if( var_CountChoices( p_input_thread, "teletext-es" ) <= 0 )
506
    {
507 508 509 510
        vlc_object_release( p_input_thread );
        return;
    }
    const bool b_selected = var_GetInteger( p_input_thread, "teletext-es" ) >= 0;
511
    if( b_selected )
512 513 514
    {
        var_SetInteger( p_input_thread, "spu-es", -1 );
    }
515 516
    else
    {
517 518
        vlc_value_t list;
        if( !var_Change( p_input_thread, "teletext-es", VLC_VAR_GETLIST, &list, NULL ) )
519
        {
520 521
            if( list.p_list->i_count > 0 )
                var_SetInteger( p_input_thread, "spu-es", list.p_list->p_values[0].i_int );
522

523
            var_FreeList( &list, NULL );
524 525 526
        }
    }
    vlc_object_release( p_input_thread );
527 528
}

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

    if( !p_input_thread )
        return -1;

537
    i_track_count = var_CountChoices( p_input_thread, "video-es" );
538

539
    vlc_object_release( p_input_thread );
540
    return i_track_count;
541 542 543
}

libvlc_track_description_t *
544
        libvlc_video_get_track_description( libvlc_media_player_t *p_mi )
545
{
546
    return libvlc_get_track_description( p_mi, "video-es" );
547 548
}

549
int libvlc_video_get_track( libvlc_media_player_t *p_mi )
550
{
551
    input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
552 553 554 555

    if( !p_input_thread )
        return -1;

556
    int id = var_GetInteger( p_input_thread, "video-es" );
557
    vlc_object_release( p_input_thread );
558
    return id;
559 560
}

561
int libvlc_video_set_track( libvlc_media_player_t *p_mi, int i_track )
562
{
563
    input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
564 565 566 567
    vlc_value_t val_list;
    int i_ret = -1;

    if( !p_input_thread )
568
        return -1;
569 570

    var_Change( p_input_thread, "video-es", VLC_VAR_GETCHOICES, &val_list, NULL );
571
    for( int i = 0; i < val_list.p_list->i_count; i++ )
572
    {
573
        if( i_track == val_list.p_list->p_values[i].i_int )
574
        {
575
            if( var_SetInteger( p_input_thread, "video-es", i_track ) < 0 )
576
                break;
577
            i_ret = 0;
578
            goto end;
579 580
        }
    }
581
    libvlc_printerr( "Track identifier not found" );
582
end:
583
    var_FreeList( &val_list, NULL );
584
    vlc_object_release( p_input_thread );
585
    return i_ret;
586
}
587 588 589 590

/******************************************************************************
 * libvlc_video_set_deinterlace : enable deinterlace
 *****************************************************************************/
591 592 593 594 595 596
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
597 598 599 600
     && 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
601
     && strcmp (psz_mode, "phosphor") && strcmp (psz_mode, "ivtc"))
602 603
        return;

604
    if (*psz_mode)
605
    {
606 607
        var_SetString (p_mi, "deinterlace-mode", psz_mode);
        var_SetInteger (p_mi, "deinterlace", 1);
608 609
    }
    else
610 611 612 613 614
        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++)
615
    {
616
        vout_thread_t *p_vout = pp_vouts[i];
617

618 619 620 621 622 623 624 625 626 627
        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);
628
}
629

630 631 632 633
/* ************** */
/* module helpers */
/* ************** */

634

635
static vlc_object_t *get_object( libvlc_media_player_t * p_mi,
636
                                 const char *name )
637
{
638 639 640
    vlc_object_t *object;
    vout_thread_t *vout = GetVout( p_mi, 0 );

641
    if( vout )
642
    {
643
        object = vlc_object_find_name( vout, name );
644 645
        vlc_object_release(vout);
    }
646 647 648
    else
        object = NULL;

649 650 651
    if( !object )
        libvlc_printerr( "%s not enabled", name );
    return object;
652 653 654
}


655
typedef const struct {
656
    const char name[20];
657
    unsigned type;
658
} opt_t;
659

660 661

static void
662 663
set_int( libvlc_media_player_t *p_mi, const char *restrict name,
         const opt_t *restrict opt, int value )
664
{
665 666 667
    if( !opt ) return;

    if( !opt->type ) /* the enabler */
668
    {
669
        vout_thread_t *vout = GetVout( p_mi, 0 );
670 671 672 673 674 675
        if (vout)
        {
            vout_EnableFilter( vout, opt->name, value, false );
            vlc_object_release( vout );
        }
        return;
676 677
    }

678 679 680 681 682
    if( opt->type != VLC_VAR_INTEGER )
    {
        libvlc_printerr( "Invalid argument to %s in %s", name, "set int" );
        return;
    }
683

684 685 686
    var_SetInteger(p_mi, opt->name, value);
    vlc_object_t *object = get_object( p_mi, name );
    if( object )
687
    {
688
        var_SetInteger(object, opt->name, value);
689
        vlc_object_release( object );
690
    }
691 692 693 694
}


static int
695 696
get_int( libvlc_media_player_t *p_mi, const char *restrict name,
         const opt_t *restrict opt )
697 698
{
    if( !opt ) return 0;
699

700
    switch( opt->type )
701
    {
702 703 704 705 706 707
        case 0: /* the enabler */
        {
            vlc_object_t *object = get_object( p_mi, name );
            vlc_object_release( object );
            return object != NULL;
        }
708
    case VLC_VAR_INTEGER:
709
        return var_GetInteger(p_mi, opt->name);
710
    default:
711 712
        libvlc_printerr( "Invalid argument to %s in %s", name, "get int" );
        return 0;
713 714 715
    }
}

716

717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756
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 );
}


757
static void
758 759
set_string( libvlc_media_player_t *p_mi, const char *restrict name,
            const opt_t *restrict opt, const char *restrict psz_value )
760
{
761 762
    if( !opt ) return;

763
    if( opt->type != VLC_VAR_STRING )
764
    {
765 766 767 768 769 770 771 772 773 774 775
        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 );
776
    }
777
}
778

779 780

static char *
781 782
get_string( libvlc_media_player_t *p_mi, const char *restrict name,
            const opt_t *restrict opt )
783 784 785
{
    if( !opt ) return NULL;

786
    if( opt->type != VLC_VAR_STRING )
787
    {
788 789
        libvlc_printerr( "Invalid argument to %s in %s", name, "get string" );
        return NULL;
790 791
    }

792 793
    return var_GetString( p_mi, opt->name );
}
794

795

796
static const opt_t *
797
marq_option_bynumber(unsigned option)
798
{
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
799
    static const opt_t optlist[] =
800 801 802 803 804 805 806 807 808 809 810 811 812
    {
        { "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) };
813

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
814
    const opt_t *r = option < num_opts ? optlist+option : NULL;
815 816 817
    if( !r )
        libvlc_printerr( "Unknown marquee option" );
    return r;
818 819
}

820
static vlc_object_t *get_object( libvlc_media_player_t *, const char *);
821

822
/*****************************************************************************
823
 * libvlc_video_get_marquee_int : get a marq option value
824
 *****************************************************************************/
825
int libvlc_video_get_marquee_int( libvlc_media_player_t *p_mi,
826
                                  unsigned option )
827
{
828
    return get_int( p_mi, "marq", marq_option_bynumber(option) );
829
}
830

831 832 833 834
/*****************************************************************************
 * libvlc_video_get_marquee_string : get a marq option value
 *****************************************************************************/
char * libvlc_video_get_marquee_string( libvlc_media_player_t *p_mi,
835
                                        unsigned option )
836
{
837
    return get_string( p_mi, "marq", marq_option_bynumber(option) );
838
}
839

840 841 842 843
/*****************************************************************************
 * libvlc_video_set_marquee_int: enable, disable or set an int option
 *****************************************************************************/
void libvlc_video_set_marquee_int( libvlc_media_player_t *p_mi,
844
                         unsigned option, int value )
845
{
846
    set_int( p_mi, "marq", marq_option_bynumber(option), value );
847
}
848

849 850 851 852
/*****************************************************************************
 * libvlc_video_set_marquee_string: set a string option
 *****************************************************************************/
void libvlc_video_set_marquee_string( libvlc_media_player_t *p_mi,
853
                unsigned option, const char * value )
854
{
855
    set_string( p_mi, "marq", marq_option_bynumber(option), value );
856 857 858
}


859
/* logo module support */
860 861


Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
862
static const opt_t *
863
logo_option_bynumber( unsigned option )
864
{
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
865 866
    static const opt_t vlogo_optlist[] =
    /* depends on libvlc_video_logo_option_t */
867 868 869 870 871 872 873 874 875 876 877 878
    {
        { "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
879
    const opt_t *r = option < num_vlogo_opts ? vlogo_optlist+option : NULL;
880
    if( !r )
881
        libvlc_printerr( "Unknown logo option" );
882 883 884 885 886
    return r;
}


void libvlc_video_set_logo_string( libvlc_media_player_t *p_mi,
887
                                   unsigned option, const char *psz_value )
888
{
889
    set_string( p_mi,"logo",logo_option_bynumber(option),psz_value );
890 891 892 893
}


void libvlc_video_set_logo_int( libvlc_media_player_t *p_mi,
894
                                unsigned option, int value )
895
{
896
    set_int( p_mi, "logo", logo_option_bynumber(option), value );
897 898 899 900
}


int libvlc_video_get_logo_int( libvlc_media_player_t *p_mi,
901
                               unsigned option )
902
{
903
    return get_int( p_mi, "logo", logo_option_bynumber(option) );
904
}
905 906


907 908 909
/* adjust module support */


Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
910
static const opt_t *
911 912 913 914 915 916 917 918 919 920 921 922 923
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
924
    const opt_t *r = option < num_opts ? optlist+option : NULL;
925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956
    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) );
}