video.c 26.7 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 556 557 558
    vlc_value_t val_list;
    vlc_value_t val;
    int i_track = -1;

    if( !p_input_thread )
        return -1;

559
    if( var_Get( p_input_thread, "video-es", &val ) < 0 )
560
    {
561
        libvlc_printerr( "Video track information not found" );
562
        vlc_object_release( p_input_thread );
563
        return -1;
564 565 566
    }

    var_Change( p_input_thread, "video-es", VLC_VAR_GETCHOICES, &val_list, NULL );
567
    for( int i = 0; i < val_list.p_list->i_count; i++ )
568
    {
569
        if( val_list.p_list->p_values[i].i_int == val.i_int )
570 571 572
        {
            i_track = i;
            break;
573
        }
574
    }
575
    var_FreeList( &val_list, NULL );
576 577 578 579
    vlc_object_release( p_input_thread );
    return i_track;
}

580
int libvlc_video_set_track( libvlc_media_player_t *p_mi, int i_track )
581
{
582
    input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
583 584 585 586
    vlc_value_t val_list;
    int i_ret = -1;

    if( !p_input_thread )
587
        return -1;
588 589

    var_Change( p_input_thread, "video-es", VLC_VAR_GETCHOICES, &val_list, NULL );
590
    for( int i = 0; i < val_list.p_list->i_count; i++ )
591
    {
592
        if( i_track == val_list.p_list->p_values[i].i_int )
593
        {
594
            if( var_SetInteger( p_input_thread, "video-es", i_track ) < 0 )
595
                break;
596
            i_ret = 0;
597
            goto end;
598 599
        }
    }
600
    libvlc_printerr( "Video track number out of range" );
601
end:
602
    var_FreeList( &val_list, NULL );
603
    vlc_object_release( p_input_thread );
604
    return i_ret;
605
}
606 607 608 609

/******************************************************************************
 * libvlc_video_set_deinterlace : enable deinterlace
 *****************************************************************************/
610 611 612 613 614 615
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
616 617 618 619
     && 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
620
     && strcmp (psz_mode, "phosphor") && strcmp (psz_mode, "ivtc"))
621 622
        return;

623
    if (*psz_mode)
624
    {
625 626
        var_SetString (p_mi, "deinterlace-mode", psz_mode);
        var_SetInteger (p_mi, "deinterlace", 1);
627 628
    }
    else
629 630 631 632 633
        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++)
634
    {
635
        vout_thread_t *p_vout = pp_vouts[i];
636

637 638 639 640 641 642 643 644 645 646
        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);
647
}
648

649 650 651 652
/* ************** */
/* module helpers */
/* ************** */

653

654
static vlc_object_t *get_object( libvlc_media_player_t * p_mi,
655
                                 const char *name )
656
{
657 658 659
    vlc_object_t *object;
    vout_thread_t *vout = GetVout( p_mi, 0 );

660
    if( vout )
661
    {
662
        object = vlc_object_find_name( vout, name );
663 664
        vlc_object_release(vout);
    }
665 666 667
    else
        object = NULL;

668 669 670
    if( !object )
        libvlc_printerr( "%s not enabled", name );
    return object;
671 672 673
}


674
typedef const struct {
675
    const char name[20];
676
    unsigned type;
677
} opt_t;
678

679 680

static void
681 682
set_int( libvlc_media_player_t *p_mi, const char *restrict name,
         const opt_t *restrict opt, int value )
683
{
684 685 686
    if( !opt ) return;

    if( !opt->type ) /* the enabler */
687
    {
688
        vout_thread_t *vout = GetVout( p_mi, 0 );
689 690 691 692 693 694
        if (vout)
        {
            vout_EnableFilter( vout, opt->name, value, false );
            vlc_object_release( vout );
        }
        return;
695 696
    }

697 698 699 700 701
    if( opt->type != VLC_VAR_INTEGER )
    {
        libvlc_printerr( "Invalid argument to %s in %s", name, "set int" );
        return;
    }
702

703 704 705
    var_SetInteger(p_mi, opt->name, value);
    vlc_object_t *object = get_object( p_mi, name );
    if( object )
706
    {
707
        var_SetInteger(object, opt->name, value);
708
        vlc_object_release( object );
709
    }
710 711 712 713
}


static int
714 715
get_int( libvlc_media_player_t *p_mi, const char *restrict name,
         const opt_t *restrict opt )
716 717
{
    if( !opt ) return 0;
718

719
    switch( opt->type )
720
    {
721 722 723 724 725 726
        case 0: /* the enabler */
        {
            vlc_object_t *object = get_object( p_mi, name );
            vlc_object_release( object );
            return object != NULL;
        }
727
    case VLC_VAR_INTEGER:
728
        return var_GetInteger(p_mi, opt->name);
729
    default:
730 731
        libvlc_printerr( "Invalid argument to %s in %s", name, "get int" );
        return 0;
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 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775
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 );
}


776
static void
777 778
set_string( libvlc_media_player_t *p_mi, const char *restrict name,
            const opt_t *restrict opt, const char *restrict psz_value )
779
{
780 781
    if( !opt ) return;

782
    if( opt->type != VLC_VAR_STRING )
783
    {
784 785 786 787 788 789 790 791 792 793 794
        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 );
795
    }
796
}
797

798 799

static char *
800 801
get_string( libvlc_media_player_t *p_mi, const char *restrict name,
            const opt_t *restrict opt )
802 803 804
{
    if( !opt ) return NULL;

805
    if( opt->type != VLC_VAR_STRING )
806
    {
807 808
        libvlc_printerr( "Invalid argument to %s in %s", name, "get string" );
        return NULL;
809 810
    }

811 812
    return var_GetString( p_mi, opt->name );
}
813

814

815
static const opt_t *
816
marq_option_bynumber(unsigned option)
817
{
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
818
    static const opt_t optlist[] =
819 820 821 822 823 824 825 826 827 828 829 830 831
    {
        { "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) };
832

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
833
    const opt_t *r = option < num_opts ? optlist+option : NULL;
834 835 836
    if( !r )
        libvlc_printerr( "Unknown marquee option" );
    return r;
837 838
}

839
static vlc_object_t *get_object( libvlc_media_player_t *, const char *);
840

841
/*****************************************************************************
842
 * libvlc_video_get_marquee_int : get a marq option value
843
 *****************************************************************************/
844
int libvlc_video_get_marquee_int( libvlc_media_player_t *p_mi,
845
                                  unsigned option )
846
{
847
    return get_int( p_mi, "marq", marq_option_bynumber(option) );
848
}
849

850 851 852 853
/*****************************************************************************
 * libvlc_video_get_marquee_string : get a marq option value
 *****************************************************************************/
char * libvlc_video_get_marquee_string( libvlc_media_player_t *p_mi,
854
                                        unsigned option )
855
{
856
    return get_string( p_mi, "marq", marq_option_bynumber(option) );
857
}
858

859 860 861 862
/*****************************************************************************
 * libvlc_video_set_marquee_int: enable, disable or set an int option
 *****************************************************************************/
void libvlc_video_set_marquee_int( libvlc_media_player_t *p_mi,
863
                         unsigned option, int value )
864
{
865
    set_int( p_mi, "marq", marq_option_bynumber(option), value );
866
}
867

868 869 870 871
/*****************************************************************************
 * libvlc_video_set_marquee_string: set a string option
 *****************************************************************************/
void libvlc_video_set_marquee_string( libvlc_media_player_t *p_mi,
872
                unsigned option, const char * value )
873
{
874
    set_string( p_mi, "marq", marq_option_bynumber(option), value );
875 876 877
}


878
/* logo module support */
879 880


Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
881
static const opt_t *
882
logo_option_bynumber( unsigned option )
883
{
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
884 885
    static const opt_t vlogo_optlist[] =
    /* depends on libvlc_video_logo_option_t */
886 887 888 889 890 891 892 893 894 895 896 897
    {
        { "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
898
    const opt_t *r = option < num_vlogo_opts ? vlogo_optlist+option : NULL;
899
    if( !r )
900
        libvlc_printerr( "Unknown logo option" );
901 902 903 904 905
    return r;
}


void libvlc_video_set_logo_string( libvlc_media_player_t *p_mi,
906
                                   unsigned option, const char *psz_value )
907
{
908
    set_string( p_mi,"logo",logo_option_bynumber(option),psz_value );
909 910 911 912
}


void libvlc_video_set_logo_int( libvlc_media_player_t *p_mi,
913
                                unsigned option, int value )
914
{
915
    set_int( p_mi, "logo", logo_option_bynumber(option), value );
916 917 918 919
}


int libvlc_video_get_logo_int( libvlc_media_player_t *p_mi,
920
                               unsigned option )
921
{
922
    return get_int( p_mi, "logo", logo_option_bynumber(option) );
923
}
924 925


926 927 928
/* adjust module support */


Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
929
static const opt_t *
930 931 932 933 934 935 936 937 938 939 940 941 942
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
943
    const opt_t *r = option < num_opts ? optlist+option : NULL;
944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975
    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) );
}