media_player.c 64.9 KB
Newer Older
1
/*****************************************************************************
2
 * media_player.c: Libvlc API Media Instance management functions
3
 *****************************************************************************
4
 * Copyright (C) 2005-2015 VLC authors and VideoLAN
5
 *
6
 * Authors: Clément Stenac <zorglub@videolan.org>
7
 *
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
8 9 10
 * 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
11 12 13 14
 * (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
Jean-Baptiste Kempf committed
15 16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
17
 *
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
18 19 20
 * 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.
21 22
 *****************************************************************************/

Geoffroy Couprie's avatar
Geoffroy Couprie committed
23 24 25 26
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

27
#include <assert.h>
28

29
#include <vlc/libvlc.h>
30
#include <vlc/libvlc_renderer_discoverer.h>
31 32 33
#include <vlc/libvlc_media.h>
#include <vlc/libvlc_events.h>

34 35
#include <vlc_demux.h>
#include <vlc_input.h>
36
#include <vlc_vout.h>
Mark Lee's avatar
Mark Lee committed
37
#include <vlc_aout.h>
38
#include <vlc_actions.h>
39 40 41 42

#include "libvlc_internal.h"
#include "media_internal.h" // libvlc_media_set_state()
#include "media_player_internal.h"
43
#include "renderer_discoverer_internal.h"
44

45 46
#define ES_INIT (-2) /* -1 is reserved for ES deselect */

47
static int
48 49 50 51 52 53 54 55
input_seekable_changed( vlc_object_t * p_this, char const * psz_cmd,
                        vlc_value_t oldval, vlc_value_t newval,
                        void * p_userdata );
static int
input_pausable_changed( vlc_object_t * p_this, char const * psz_cmd,
                        vlc_value_t oldval, vlc_value_t newval,
                        void * p_userdata );
static int
56 57 58 59
input_scrambled_changed( vlc_object_t * p_this, char const * psz_cmd,
                        vlc_value_t oldval, vlc_value_t newval,
                        void * p_userdata );
static int
Laurent Aimar's avatar
Laurent Aimar committed
60
input_event_changed( vlc_object_t * p_this, char const * psz_cmd,
61 62 63
                     vlc_value_t oldval, vlc_value_t newval,
                     void * p_userdata );

64 65 66 67 68
static int
input_es_changed( vlc_object_t * p_this, char const * psz_cmd,
                  int action, vlc_value_t *p_val,
                  void *p_userdata);

69 70 71 72
static int
corks_changed(vlc_object_t *obj, const char *name, vlc_value_t old,
              vlc_value_t cur, void *opaque);

73 74 75 76
static int
mute_changed(vlc_object_t *obj, const char *name, vlc_value_t old,
             vlc_value_t cur, void *opaque);

77 78 79 80
static int
volume_changed(vlc_object_t *obj, const char *name, vlc_value_t old,
               vlc_value_t cur, void *opaque);

81 82 83 84 85 86
static void
add_es_callbacks( input_thread_t *p_input_thread, libvlc_media_player_t *p_mi );

static void
del_es_callbacks( input_thread_t *p_input_thread, libvlc_media_player_t *p_mi );

87 88 89
static int
snapshot_was_taken( vlc_object_t *p_this, char const *psz_cmd,
                    vlc_value_t oldval, vlc_value_t newval, void *p_data );
90

91
static void libvlc_media_player_destroy( libvlc_media_player_t *p_mi );
92

93 94 95 96
/*
 * Shortcuts
 */

97 98 99 100 101 102 103 104 105
/*
 * The input lock protects the input and input resource pointer.
 * It MUST NOT be used from callbacks.
 *
 * The object lock protects the reset, namely the media and the player state.
 * It can, and usually needs to be taken from callbacks.
 * The object lock can be acquired under the input lock... and consequently
 * the opposite order is STRICTLY PROHIBITED.
 */
106 107 108 109 110 111 112 113 114 115
static inline void lock(libvlc_media_player_t *mp)
{
    vlc_mutex_lock(&mp->object_lock);
}

static inline void unlock(libvlc_media_player_t *mp)
{
    vlc_mutex_unlock(&mp->object_lock);
}

116 117 118 119 120 121 122 123 124 125
static inline void lock_input(libvlc_media_player_t *mp)
{
    vlc_mutex_lock(&mp->input.lock);
}

static inline void unlock_input(libvlc_media_player_t *mp)
{
    vlc_mutex_unlock(&mp->input.lock);
}

126 127 128 129 130 131 132 133 134 135
static void input_item_preparsed_changed( const vlc_event_t *p_event,
                                          void * user_data )
{
    libvlc_media_t *p_md = user_data;
    if( p_event->u.input_item_preparsed_changed.new_status & ITEM_PREPARSED )
    {
        /* Send the event */
        libvlc_event_t event;
        event.type = libvlc_MediaParsedChanged;
        event.u.media_parsed_changed.new_status = libvlc_media_parsed_status_done;
136
        libvlc_event_send( &p_md->event_manager, &event );
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
    }
}

static void media_attach_preparsed_event( libvlc_media_t *p_md )
{
    vlc_event_attach( &p_md->p_input_item->event_manager,
                      vlc_InputItemPreparsedChanged,
                      input_item_preparsed_changed, p_md );
}

static void media_detach_preparsed_event( libvlc_media_t *p_md )
{
    vlc_event_detach( &p_md->p_input_item->event_manager,
                      vlc_InputItemPreparsedChanged,
                      input_item_preparsed_changed,
                      p_md );
}

155
/*
156
 * Release the associated input thread.
157 158
 *
 * Object lock is NOT held.
159
 * Input lock is held or instance is being destroyed.
160
 */
161
static void release_input_thread( libvlc_media_player_t *p_mi )
162
{
163
    assert( p_mi );
164

165
    input_thread_t *p_input_thread = p_mi->input.p_thread;
166
    if( !p_input_thread )
167
        return;
168
    p_mi->input.p_thread = NULL;
169

170 171
    media_detach_preparsed_event( p_mi->p_md );

172 173 174 175
    var_DelCallback( p_input_thread, "can-seek",
                     input_seekable_changed, p_mi );
    var_DelCallback( p_input_thread, "can-pause",
                    input_pausable_changed, p_mi );
176 177
    var_DelCallback( p_input_thread, "program-scrambled",
                    input_scrambled_changed, p_mi );
178 179
    var_DelCallback( p_input_thread, "intf-event",
                     input_event_changed, p_mi );
180
    del_es_callbacks( p_input_thread, p_mi );
181 182

    /* We owned this one */
183
    input_Stop( p_input_thread );
184
    input_Close( p_input_thread );
185 186
}

187 188
/*
 * Retrieve the input thread. Be sure to release the object
189
 * once you are done with it. (libvlc Internal)
190
 */
191
input_thread_t *libvlc_get_input_thread( libvlc_media_player_t *p_mi )
192 193 194
{
    input_thread_t *p_input_thread;

195
    assert( p_mi );
196

197 198
    lock_input(p_mi);
    p_input_thread = p_mi->input.p_thread;
199 200
    if( p_input_thread )
        vlc_object_hold( p_input_thread );
201 202
    else
        libvlc_printerr( "No active input" );
203
    unlock_input(p_mi);
204

205 206 207
    return p_input_thread;
}

208 209 210 211 212
/*
 * Set the internal state of the media_player. (media player Internal)
 *
 * Function will lock the media_player.
 */
213 214 215 216 217
static void set_state( libvlc_media_player_t *p_mi, libvlc_state_t state,
    bool b_locked )
{
    if(!b_locked)
        lock(p_mi);
218
    p_mi->state = state;
219

220 221 222
    libvlc_media_t *media = p_mi->p_md;
    if (media)
        libvlc_media_retain(media);
223

224 225
    if(!b_locked)
        unlock(p_mi);
226

227 228
    if (media)
    {
229 230 231
        // Also set the state of the corresponding media
        // This is strictly for convenience.
        libvlc_media_set_state(media, state);
232 233

        libvlc_media_release(media);
234 235 236
    }
}

237
static int
238
input_seekable_changed( vlc_object_t * p_this, char const * psz_cmd,
239 240 241 242
                        vlc_value_t oldval, vlc_value_t newval,
                        void * p_userdata )
{
    VLC_UNUSED(oldval);
243 244
    VLC_UNUSED(p_this);
    VLC_UNUSED(psz_cmd);
245
    libvlc_media_player_t * p_mi = p_userdata;
246 247
    libvlc_event_t event;

248
    event.type = libvlc_MediaPlayerSeekableChanged;
249
    event.u.media_player_seekable_changed.new_seekable = newval.b_bool;
250

251
    libvlc_event_send( &p_mi->event_manager, &event );
252 253 254 255 256 257 258 259 260
    return VLC_SUCCESS;
}

static int
input_pausable_changed( vlc_object_t * p_this, char const * psz_cmd,
                        vlc_value_t oldval, vlc_value_t newval,
                        void * p_userdata )
{
    VLC_UNUSED(oldval);
261 262
    VLC_UNUSED(p_this);
    VLC_UNUSED(psz_cmd);
263
    libvlc_media_player_t * p_mi = p_userdata;
264 265
    libvlc_event_t event;

266
    event.type = libvlc_MediaPlayerPausableChanged;
267
    event.u.media_player_pausable_changed.new_pausable = newval.b_bool;
268

269
    libvlc_event_send( &p_mi->event_manager, &event );
270 271 272
    return VLC_SUCCESS;
}

273 274 275 276 277 278 279 280 281 282 283 284 285 286
static int
input_scrambled_changed( vlc_object_t * p_this, char const * psz_cmd,
                        vlc_value_t oldval, vlc_value_t newval,
                        void * p_userdata )
{
    VLC_UNUSED(oldval);
    VLC_UNUSED(p_this);
    VLC_UNUSED(psz_cmd);
    libvlc_media_player_t * p_mi = p_userdata;
    libvlc_event_t event;

    event.type = libvlc_MediaPlayerScrambledChanged;
    event.u.media_player_scrambled_changed.new_scrambled = newval.b_bool;

287
    libvlc_event_send( &p_mi->event_manager, &event );
288 289 290
    return VLC_SUCCESS;
}

291
static int
Laurent Aimar's avatar
Laurent Aimar committed
292
input_event_changed( vlc_object_t * p_this, char const * psz_cmd,
293 294 295
                     vlc_value_t oldval, vlc_value_t newval,
                     void * p_userdata )
{
296
    VLC_UNUSED(oldval); VLC_UNUSED(psz_cmd);
Laurent Aimar's avatar
Laurent Aimar committed
297
    input_thread_t * p_input = (input_thread_t *)p_this;
298
    libvlc_media_player_t * p_mi = p_userdata;
Laurent Aimar's avatar
Laurent Aimar committed
299
    libvlc_event_t event;
300

301
    assert( !strcmp( psz_cmd, "intf-event" ) );
302

303 304
    if( newval.i_int == INPUT_EVENT_STATE )
    {
305
        libvlc_state_t libvlc_state;
306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336

        switch ( var_GetInteger( p_input, "state" ) )
        {
            case INIT_S:
                libvlc_state = libvlc_NothingSpecial;
                event.type = libvlc_MediaPlayerNothingSpecial;
                break;
            case OPENING_S:
                libvlc_state = libvlc_Opening;
                event.type = libvlc_MediaPlayerOpening;
                break;
            case PLAYING_S:
                libvlc_state = libvlc_Playing;
                event.type = libvlc_MediaPlayerPlaying;
                break;
            case PAUSE_S:
                libvlc_state = libvlc_Paused;
                event.type = libvlc_MediaPlayerPaused;
                break;
            case END_S:
                libvlc_state = libvlc_Ended;
                event.type = libvlc_MediaPlayerEndReached;
                break;
            case ERROR_S:
                libvlc_state = libvlc_Error;
                event.type = libvlc_MediaPlayerEncounteredError;
                break;

            default:
                return VLC_SUCCESS;
        }
337

338
        set_state( p_mi, libvlc_state, false );
339
        libvlc_event_send( &p_mi->event_manager, &event );
340
    }
341
    else if( newval.i_int == INPUT_EVENT_DEAD )
342
    {
343
        libvlc_state_t libvlc_state = libvlc_Ended;
344 345
        event.type = libvlc_MediaPlayerStopped;

346
        set_state( p_mi, libvlc_state, false );
347
        libvlc_event_send( &p_mi->event_manager, &event );
348
    }
349
    else if( newval.i_int == INPUT_EVENT_POSITION )
350 351 352 353 354 355
    {
        if( var_GetInteger( p_input, "state" ) != PLAYING_S )
            return VLC_SUCCESS; /* Don't send the position while stopped */

        /* */
        event.type = libvlc_MediaPlayerPositionChanged;
356 357
        event.u.media_player_position_changed.new_position =
                                          var_GetFloat( p_input, "position" );
358
        libvlc_event_send( &p_mi->event_manager, &event );
359 360 361

        /* */
        event.type = libvlc_MediaPlayerTimeChanged;
362
        event.u.media_player_time_changed.new_time =
363
           from_mtime(var_GetInteger( p_input, "time" ));
364
        libvlc_event_send( &p_mi->event_manager, &event );
365
    }
366 367 368 369
    else if( newval.i_int == INPUT_EVENT_LENGTH )
    {
        event.type = libvlc_MediaPlayerLengthChanged;
        event.u.media_player_length_changed.new_length =
370
           from_mtime(var_GetInteger( p_input, "length" ));
371
        libvlc_event_send( &p_mi->event_manager, &event );
372
    }
373 374 375
    else if( newval.i_int == INPUT_EVENT_CACHE )
    {
        event.type = libvlc_MediaPlayerBuffering;
376
        event.u.media_player_buffering.new_cache = (100 *
377
            var_GetFloat( p_input, "cache" ));
378
        libvlc_event_send( &p_mi->event_manager, &event );
379
    }
380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396
    else if( newval.i_int == INPUT_EVENT_VOUT )
    {
        vout_thread_t **pp_vout;
        size_t i_vout;
        if( input_Control( p_input, INPUT_GET_VOUTS, &pp_vout, &i_vout ) )
        {
            i_vout  = 0;
        }
        else
        {
            for( size_t i = 0; i < i_vout; i++ )
                vlc_object_release( pp_vout[i] );
            free( pp_vout );
        }

        event.type = libvlc_MediaPlayerVout;
        event.u.media_player_vout.new_count = i_vout;
397
        libvlc_event_send( &p_mi->event_manager, &event );
398
    }
399 400 401 402
    else if ( newval.i_int == INPUT_EVENT_TITLE )
    {
        event.type = libvlc_MediaPlayerTitleChanged;
        event.u.media_player_title_changed.new_title = var_GetInteger( p_input, "title" );
403
        libvlc_event_send( &p_mi->event_manager, &event );
404
    }
405 406 407 408
    else if ( newval.i_int == INPUT_EVENT_CHAPTER )
    {
        event.type = libvlc_MediaPlayerChapterChanged;
        event.u.media_player_chapter_changed.new_chapter = var_GetInteger( p_input, "chapter" );
409
        libvlc_event_send( &p_mi->event_manager, &event );
410
    }
411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443
    else if ( newval.i_int == INPUT_EVENT_ES )
    {
        /* Send ESSelected events from this callback ("intf-event") and not
         * from "audio-es", "video-es", "spu-es" callbacks. Indeed, these
         * callbacks are not triggered when the input_thread changes an ES
         * while this callback is. */
        struct {
            const char *psz_name;
            const libvlc_track_type_t type;
            int new_es;
        } es_list[] = {
            { "audio-es", libvlc_track_audio, ES_INIT },
            { "video-es", libvlc_track_video, ES_INIT },
            { "spu-es", libvlc_track_text, ES_INIT },
        };
        /* Check if an ES selection changed */
        lock( p_mi );
        for( size_t i = 0; i < ARRAY_SIZE( es_list ); ++i )
        {
            int current_es = var_GetInteger( p_input, es_list[i].psz_name );
            if( current_es != p_mi->selected_es[i] )
                es_list[i].new_es = p_mi->selected_es[i] = current_es;
        }
        unlock( p_mi );

        /* Send the ESSelected event for each ES that were newly selected */
        for( size_t i = 0; i < ARRAY_SIZE( es_list ); ++i )
        {
            if( es_list[i].new_es != ES_INIT )
            {
                event.type = libvlc_MediaPlayerESSelected;
                event.u.media_player_es_changed.i_type = es_list[i].type;
                event.u.media_player_es_changed.i_id = es_list[i].new_es;
444
                libvlc_event_send( &p_mi->event_manager, &event );
445 446 447
            }
        }
    }
Laurent Aimar's avatar
Laurent Aimar committed
448

449 450 451
    return VLC_SUCCESS;
}

452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506
static int track_type_from_name(const char *psz_name)
{
   if( !strcmp( psz_name, "video-es" ) )
       return libvlc_track_video;
    else if( !strcmp( psz_name, "audio-es" ) )
        return libvlc_track_audio;
    else if( !strcmp( psz_name, "spu-es" ) )
        return libvlc_track_text;
    else
        return libvlc_track_unknown;
}

static int input_es_changed( vlc_object_t *p_this,
                             char const *psz_cmd,
                             int action,
                             vlc_value_t *p_val,
                             void *p_userdata )
{
    VLC_UNUSED(p_this);
    libvlc_media_player_t *mp = p_userdata;
    libvlc_event_t event;

    /* Ignore the "Disable" element */
    if (p_val && p_val->i_int < 0)
        return VLC_EGENERIC;

    switch (action)
    {
    case VLC_VAR_ADDCHOICE:
        event.type = libvlc_MediaPlayerESAdded;
        break;
    case VLC_VAR_DELCHOICE:
    case VLC_VAR_CLEARCHOICES:
        event.type = libvlc_MediaPlayerESDeleted;
        break;
    default:
        return VLC_EGENERIC;
    }

    event.u.media_player_es_changed.i_type = track_type_from_name(psz_cmd);

    int i_id;
    if (action != VLC_VAR_CLEARCHOICES)
    {
        if (!p_val)
            return VLC_EGENERIC;
        i_id = p_val->i_int;
    }
    else
    {
        /* -1 means all ES tracks of this type were deleted. */
        i_id = -1;
    }
    event.u.media_player_es_changed.i_id = i_id;

507
    libvlc_event_send(&mp->event_manager, &event);
508 509 510 511

    return VLC_SUCCESS;
}

512 513 514 515 516 517 518 519 520 521 522 523 524 525
/**************************************************************************
 * Snapshot Taken Event.
 *
 * FIXME: This snapshot API interface makes no sense in media_player.
 *************************************************************************/
static int snapshot_was_taken(vlc_object_t *p_this, char const *psz_cmd,
                              vlc_value_t oldval, vlc_value_t newval, void *p_data )
{
    VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval); VLC_UNUSED(p_this);

    libvlc_media_player_t *mp = p_data;
    libvlc_event_t event;
    event.type = libvlc_MediaPlayerSnapshotTaken;
    event.u.media_player_snapshot_taken.psz_filename = newval.psz_string;
526
    libvlc_event_send(&mp->event_manager, &event);
527 528 529 530

    return VLC_SUCCESS;
}

531 532 533 534 535 536 537 538 539 540 541
static int corks_changed(vlc_object_t *obj, const char *name, vlc_value_t old,
                         vlc_value_t cur, void *opaque)
{
    libvlc_media_player_t *mp = (libvlc_media_player_t *)obj;

    if (!old.i_int != !cur.i_int)
    {
        libvlc_event_t event;

        event.type = cur.i_int ? libvlc_MediaPlayerCorked
                               : libvlc_MediaPlayerUncorked;
542
        libvlc_event_send(&mp->event_manager, &event);
543 544 545 546 547
    }
    VLC_UNUSED(name); VLC_UNUSED(opaque);
    return VLC_SUCCESS;
}

548 549 550 551 552 553 554 555
static int audio_device_changed(vlc_object_t *obj, const char *name,
                                vlc_value_t old, vlc_value_t cur, void *opaque)
{
    libvlc_media_player_t *mp = (libvlc_media_player_t *)obj;
    libvlc_event_t event;

    event.type = libvlc_MediaPlayerAudioDevice;
    event.u.media_player_audio_device.device = cur.psz_string;
556
    libvlc_event_send(&mp->event_manager, &event);
557 558 559 560
    VLC_UNUSED(name); VLC_UNUSED(old); VLC_UNUSED(opaque);
    return VLC_SUCCESS;
}

561 562 563 564 565 566 567 568 569 570 571
static int mute_changed(vlc_object_t *obj, const char *name, vlc_value_t old,
                        vlc_value_t cur, void *opaque)
{
    libvlc_media_player_t *mp = (libvlc_media_player_t *)obj;

    if (old.b_bool != cur.b_bool)
    {
        libvlc_event_t event;

        event.type = cur.b_bool ? libvlc_MediaPlayerMuted
                                : libvlc_MediaPlayerUnmuted;
572
        libvlc_event_send(&mp->event_manager, &event);
573 574 575 576 577
    }
    VLC_UNUSED(name); VLC_UNUSED(opaque);
    return VLC_SUCCESS;
}

578 579 580 581 582 583 584 585
static int volume_changed(vlc_object_t *obj, const char *name, vlc_value_t old,
                          vlc_value_t cur, void *opaque)
{
    libvlc_media_player_t *mp = (libvlc_media_player_t *)obj;
    libvlc_event_t event;

    event.type = libvlc_MediaPlayerAudioVolume;
    event.u.media_player_audio_volume.volume = cur.f_float;
586
    libvlc_event_send(&mp->event_manager, &event);
587 588 589 590
    VLC_UNUSED(name); VLC_UNUSED(old); VLC_UNUSED(opaque);
    return VLC_SUCCESS;
}

591
/**************************************************************************
592 593 594 595 596 597 598 599 600 601 602 603
 * Create a Media Instance object.
 *
 * Refcount strategy:
 * - All items created by _new start with a refcount set to 1.
 * - Accessor _release decrease the refcount by 1, if after that
 *   operation the refcount is 0, the object is destroyed.
 * - Accessor _retain increase the refcount by 1 (XXX: to implement)
 *
 * Object locking strategy:
 * - No lock held while in constructor.
 * - When accessing any member variable this lock is held. (XXX who locks?)
 * - When attempting to destroy the object the lock is also held.
604
 **************************************************************************/
605
libvlc_media_player_t *
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
606
libvlc_media_player_new( libvlc_instance_t *instance )
607
{
608
    libvlc_media_player_t * mp;
609

610
    assert(instance);
611

612 613
    mp = vlc_object_create (instance->p_libvlc_int, sizeof(*mp));
    if (unlikely(mp == NULL))
614
    {
615
        libvlc_printerr("Not enough memory");
616 617
        return NULL;
    }
618

619 620
    /* Input */
    var_Create (mp, "rate", VLC_VAR_FLOAT|VLC_VAR_DOINHERIT);
621 622
    var_Create (mp, "sout", VLC_VAR_STRING);
    var_Create (mp, "demux-filter", VLC_VAR_STRING);
623

624
    /* Video */
625
    var_Create (mp, "vout", VLC_VAR_STRING|VLC_VAR_DOINHERIT);
626
    var_Create (mp, "window", VLC_VAR_STRING);
627 628 629 630
    var_Create (mp, "vmem-lock", VLC_VAR_ADDRESS);
    var_Create (mp, "vmem-unlock", VLC_VAR_ADDRESS);
    var_Create (mp, "vmem-display", VLC_VAR_ADDRESS);
    var_Create (mp, "vmem-data", VLC_VAR_ADDRESS);
631 632
    var_Create (mp, "vmem-setup", VLC_VAR_ADDRESS);
    var_Create (mp, "vmem-cleanup", VLC_VAR_ADDRESS);
633 634 635
    var_Create (mp, "vmem-chroma", VLC_VAR_STRING | VLC_VAR_DOINHERIT);
    var_Create (mp, "vmem-width", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
    var_Create (mp, "vmem-height", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
636
    var_Create (mp, "vmem-pitch", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
637
    var_Create (mp, "avcodec-hw", VLC_VAR_STRING);
638
    var_Create (mp, "drawable-xid", VLC_VAR_INTEGER);
639
#if defined (_WIN32) || defined (__OS2__)
640
    var_Create (mp, "drawable-hwnd", VLC_VAR_INTEGER);
641 642 643 644
#endif
#ifdef __APPLE__
    var_Create (mp, "drawable-nsobject", VLC_VAR_ADDRESS);
#endif
645 646 647
#ifdef __ANDROID__
    var_Create (mp, "drawable-androidwindow", VLC_VAR_ADDRESS);
#endif
648 649 650
#ifdef HAVE_EVAS
    var_Create (mp, "drawable-evasobject", VLC_VAR_ADDRESS);
#endif
651 652 653 654

    var_Create (mp, "keyboard-events", VLC_VAR_BOOL);
    var_SetBool (mp, "keyboard-events", true);
    var_Create (mp, "mouse-events", VLC_VAR_BOOL);
655
    var_SetBool (mp, "mouse-events", true);
656

657
    var_Create (mp, "fullscreen", VLC_VAR_BOOL);
658 659
    var_Create (mp, "autoscale", VLC_VAR_BOOL | VLC_VAR_DOINHERIT);
    var_Create (mp, "zoom", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT);
660 661
    var_Create (mp, "aspect-ratio", VLC_VAR_STRING);
    var_Create (mp, "crop", VLC_VAR_STRING);
662 663
    var_Create (mp, "deinterlace", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
    var_Create (mp, "deinterlace-mode", VLC_VAR_STRING | VLC_VAR_DOINHERIT);
664

665
    var_Create (mp, "vbi-page", VLC_VAR_INTEGER);
666
    var_SetInteger (mp, "vbi-page", 100);
667

668 669 670 671
    var_Create (mp, "video-filter", VLC_VAR_STRING | VLC_VAR_DOINHERIT);
    var_Create (mp, "sub-source", VLC_VAR_STRING | VLC_VAR_DOINHERIT);
    var_Create (mp, "sub-filter", VLC_VAR_STRING | VLC_VAR_DOINHERIT);

672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689
    var_Create (mp, "marq-marquee", VLC_VAR_STRING);
    var_Create (mp, "marq-color", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
    var_Create (mp, "marq-opacity", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
    var_Create (mp, "marq-position", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
    var_Create (mp, "marq-refresh", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
    var_Create (mp, "marq-size", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
    var_Create (mp, "marq-timeout", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
    var_Create (mp, "marq-x", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
    var_Create (mp, "marq-y", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);

    var_Create (mp, "logo-file", VLC_VAR_STRING);
    var_Create (mp, "logo-x", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
    var_Create (mp, "logo-y", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
    var_Create (mp, "logo-delay", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
    var_Create (mp, "logo-repeat", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
    var_Create (mp, "logo-opacity", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
    var_Create (mp, "logo-position", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);

690 691
    var_Create (mp, "contrast", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT);
    var_Create (mp, "brightness", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT);
692
    var_Create (mp, "hue", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT);
693 694 695
    var_Create (mp, "saturation", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT);
    var_Create (mp, "gamma", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT);

696
     /* Audio */
697
    var_Create (mp, "aout", VLC_VAR_STRING | VLC_VAR_DOINHERIT);
698
    var_Create (mp, "audio-device", VLC_VAR_STRING);
699
    var_Create (mp, "mute", VLC_VAR_BOOL);
700
    var_Create (mp, "volume", VLC_VAR_FLOAT);
701
    var_Create (mp, "corks", VLC_VAR_INTEGER);
702
    var_Create (mp, "audio-filter", VLC_VAR_STRING);
703
    var_Create (mp, "role", VLC_VAR_STRING | VLC_VAR_DOINHERIT);
704 705
    var_Create (mp, "amem-data", VLC_VAR_ADDRESS);
    var_Create (mp, "amem-setup", VLC_VAR_ADDRESS);
Sébastien Toque's avatar
Sébastien Toque committed
706
    var_Create (mp, "amem-cleanup", VLC_VAR_ADDRESS);
707
    var_Create (mp, "amem-play", VLC_VAR_ADDRESS);
708 709 710 711
    var_Create (mp, "amem-pause", VLC_VAR_ADDRESS);
    var_Create (mp, "amem-resume", VLC_VAR_ADDRESS);
    var_Create (mp, "amem-flush", VLC_VAR_ADDRESS);
    var_Create (mp, "amem-drain", VLC_VAR_ADDRESS);
712 713 714 715
    var_Create (mp, "amem-set-volume", VLC_VAR_ADDRESS);
    var_Create (mp, "amem-format", VLC_VAR_STRING | VLC_VAR_DOINHERIT);
    var_Create (mp, "amem-rate", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
    var_Create (mp, "amem-channels", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
716

717 718 719 720 721
    /* Video Title */
    var_Create (mp, "video-title-show", VLC_VAR_BOOL);
    var_Create (mp, "video-title-position", VLC_VAR_INTEGER);
    var_Create (mp, "video-title-timeout", VLC_VAR_INTEGER);

Mark Lee's avatar
Mark Lee committed
722 723
    /* Equalizer */
    var_Create (mp, "equalizer-preamp", VLC_VAR_FLOAT);
724
    var_Create (mp, "equalizer-vlcfreqs", VLC_VAR_BOOL);
Mark Lee's avatar
Mark Lee committed
725 726
    var_Create (mp, "equalizer-bands", VLC_VAR_STRING);

727
    mp->p_md = NULL;
728
    mp->state = libvlc_NothingSpecial;
729
    mp->p_libvlc_instance = instance;
730
    mp->input.p_thread = NULL;
731
    mp->input.p_renderer = NULL;
732 733 734 735 736 737
    mp->input.p_resource = input_resource_New(VLC_OBJECT(mp));
    if (unlikely(mp->input.p_resource == NULL))
    {
        vlc_object_release(mp);
        return NULL;
    }
738 739 740 741
    audio_output_t *aout = input_resource_GetAout(mp->input.p_resource);
    if( aout != NULL )
        input_resource_PutAout(mp->input.p_resource, aout);

742 743 744 745
    vlc_viewpoint_init(&mp->viewpoint);

    var_Create (mp, "viewpoint", VLC_VAR_ADDRESS);
    var_SetAddress( mp, "viewpoint", &mp->viewpoint );
746
    vlc_mutex_init (&mp->input.lock);
747
    mp->i_refcount = 1;
748
    libvlc_event_manager_init(&mp->event_manager, mp);
749
    vlc_mutex_init(&mp->object_lock);
750

751
    var_AddCallback(mp, "corks", corks_changed, NULL);
752
    var_AddCallback(mp, "audio-device", audio_device_changed, NULL);
753
    var_AddCallback(mp, "mute", mute_changed, NULL);
754
    var_AddCallback(mp, "volume", volume_changed, NULL);
755

756 757
    /* Snapshot initialization */
    /* Attach a var callback to the global object to provide the glue between
758 759 760 761 762 763
     * vout_thread that generates the event and media_player that re-emits it
     * with its own event manager
     *
     * FIXME: It's unclear why we want to put this in public API, and why we
     * want to expose it in such a limiting and ugly way.
     */
764
    var_AddCallback(mp->obj.libvlc, "snapshot-file", snapshot_was_taken, mp);
765

766
    libvlc_retain(instance);
767
    return mp;
768 769 770
}

/**************************************************************************
771
 * Create a Media Instance object with a media descriptor.
772
 **************************************************************************/
773
libvlc_media_player_t *
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
774
libvlc_media_player_new_from_media( libvlc_media_t * p_md )
775
{
776
    libvlc_media_player_t * p_mi;
777

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
778
    p_mi = libvlc_media_player_new( p_md->p_libvlc_instance );
779
    if( !p_mi )
780 781
        return NULL;

782
    libvlc_media_retain( p_md );
783
    p_mi->p_md = p_md;
784 785 786 787 788

    return p_mi;
}

/**************************************************************************
789
 * Destroy a Media Instance object (libvlc internal)
790
 *
791
 * Warning: No lock held here, but hey, this is internal. Caller must lock.
792
 **************************************************************************/
793
static void libvlc_media_player_destroy( libvlc_media_player_t *p_mi )
794
{
795
    assert( p_mi );
796

797
    /* Detach Callback from the main libvlc object */
798
    var_DelCallback( p_mi->obj.libvlc,
799
                     "snapshot-file", snapshot_was_taken, p_mi );
800

801
    /* Detach callback from the media player / input manager object */
802
    var_DelCallback( p_mi, "volume", volume_changed, NULL );
803
    var_DelCallback( p_mi, "mute", mute_changed, NULL );
804
    var_DelCallback( p_mi, "audio-device", audio_device_changed, NULL );
805 806
    var_DelCallback( p_mi, "corks", corks_changed, NULL );

807 808
    /* No need for lock_input() because no other threads knows us anymore */
    if( p_mi->input.p_thread )
809
        release_input_thread(p_mi);
810 811
    input_resource_Terminate( p_mi->input.p_resource );
    input_resource_Release( p_mi->input.p_resource );
812 813 814
    if( p_mi->input.p_renderer )
        vlc_renderer_item_release( p_mi->input.p_renderer );

815
    vlc_mutex_destroy( &p_mi->input.lock );
816

817
    libvlc_event_manager_destroy(&p_mi->event_manager);
818
    libvlc_media_release( p_mi->p_md );
819
    vlc_mutex_destroy( &p_mi->object_lock );
820 821

    libvlc_instance_t *instance = p_mi->p_libvlc_instance;
822
    vlc_object_release( p_mi );
823
    libvlc_release(instance);
824 825 826
}

/**************************************************************************
827 828 829
 * Release a Media Instance object.
 *
 * Function does the locking.
830
 **************************************************************************/
831
void libvlc_media_player_release( libvlc_media_player_t *p_mi )
832
{
833
    bool destroy;
834

835
    assert( p_mi );
836
    lock(p_mi);
837
    destroy = !--p_mi->i_refcount;
838
    unlock(p_mi);
839

840 841
    if( destroy )
        libvlc_media_player_destroy( p_mi );
842
}
843

844
/**************************************************************************
845 846 847
 * Retain a Media Instance object.
 *
 * Caller must hold the lock.
848
 **************************************************************************/
849
void libvlc_media_player_retain( libvlc_media_player_t *p_mi )
850
{
851
    assert( p_mi );
852

853
    lock(p_mi);
854
    p_mi->i_refcount++;
855
    unlock(p_mi);
856
}
857

858
/**************************************************************************
859 860 861
 * Set the Media descriptor associated with the instance.
 *
 * Enter without lock -- function will lock the object.
862
 **************************************************************************/
863 864
void libvlc_media_player_set_media(
                            libvlc_media_player_t *p_mi,
865
                            libvlc_media_t *p_md )
866
{
867
    lock_input(p_mi);
868

869
    release_input_thread( p_mi );
870

871
    lock( p_mi );
872
    set_state( p_mi, libvlc_NothingSpecial, true );
873
    unlock_input( p_mi );
874

875
    libvlc_media_release( p_mi->p_md );
876

877 878 879
    if( !p_md )
    {
        p_mi->p_md = NULL;
880
        unlock(p_mi);
881 882 883
        return; /* It is ok to pass a NULL md */
    }

884
    libvlc_media_retain( p_md );
885
    p_mi->p_md = p_md;
886

887 888 889 890
    /* The policy here is to ignore that we were created using a different
     * libvlc_instance, because we don't really care */
    p_mi->p_libvlc_instance = p_md->p_libvlc_instance;

891
    unlock(p_mi);
892 893 894 895 896

    /* Send an event for the newly available media */
    libvlc_event_t event;
    event.type = libvlc_MediaPlayerMediaChanged;
    event.u.media_player_media_changed.new_media = p_md;
897
    libvlc_event_send( &p_mi->event_manager, &event );
898

899 900 901
}

/**************************************************************************
902
 * Get the Media descriptor associated with the instance.
903
 **************************************************************************/
904
libvlc_media_t *
905
libvlc_media_player_get_media( libvlc_media_player_t *p_mi )
906
{
907
    libvlc_media_t *p_m;
908

909
    lock( p_mi );
910 911
    p_m = p_mi->p_md;
    if( p_m )
912 913 914 915
        libvlc_media_retain( p_m );
    unlock( p_mi );

    return p_m;
916 917
}

918
/**************************************************************************
919
 * Get the event Manager.
920 921
 **************************************************************************/
libvlc_event_manager_t *
922
libvlc_media_player_event_manager( libvlc_media_player_t *p_mi )
923
{
924
    return &p_mi->event_manager;
925 926
}

927 928 929 930 931 932 933 934 935 936 937 938 939 940
static void add_es_callbacks( input_thread_t *p_input_thread, libvlc_media_player_t *p_mi )
{
    var_AddListCallback( p_input_thread, "video-es", input_es_changed, p_mi );
    var_AddListCallback( p_input_thread, "audio-es", input_es_changed, p_mi );
    var_AddListCallback( p_input_thread, "spu-es", input_es_changed, p_mi );
}

static void del_es_callbacks( input_thread_t *p_input_thread, libvlc_media_player_t *p_mi )
{
    var_DelListCallback( p_input_thread, "video-es", input_es_changed, p_mi );
    var_DelListCallback( p_input_thread, "audio-es", input_es_changed, p_mi );
    var_DelListCallback( p_input_thread, "spu-es", input_es_changed, p_mi );
}

941
/**************************************************************************
942
 * Tell media player to start playing.
943
 **************************************************************************/
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
944
int libvlc_media_player_play( libvlc_media_player_t *p_mi )
945
{
946
    lock_input( p_mi );
947

948 949
    input_thread_t *p_input_thread = p_mi->input.p_thread;
    if( p_input_thread )
950
    {
Sam Hocevar's avatar
Sam Hocevar committed
951
        /* A thread already exists, send it a play message */
952
        input_Control( p_input_thread, INPUT_SET_STATE, PLAYING_S );
953
        unlock_input( p_mi );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
954
        return 0;
955 956
    }

957
    /* Ignore previous exception */
958
    lock(p_mi);
959

960 961
    if( !p_mi->p_md )
    {
962
        unlock(p_mi);
963
        unlock_input( p_mi );
964
        libvlc_printerr( "No associated media descriptor" );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
965
        return -1;
966 967
    }

968 969 970
    for( size_t i = 0; i < ARRAY_SIZE( p_mi->selected_es ); ++i )
        p_mi->selected_es[i] = ES_INIT;

971 972
    media_attach_preparsed_event( p_mi->p_md );

973
    p_input_thread = input_Create( p_mi, p_mi->p_md->p_input_item, NULL,
974 975
                                   p_mi->input.p_resource,
                                   p_mi->input.p_renderer );
976 977
    unlock(p_mi);
    if( !p_input_thread )
978
    {
979
        unlock_input(p_mi);
980
        media_detach_preparsed_event( p_mi->p_md );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
981 982
        libvlc_printerr( "Not enough memory" );
        return -1;
983
    }
984

985 986
    var_AddCallback( p_input_thread, "can-seek", input_seekable_changed, p_mi );
    var_AddCallback( p_input_thread, "can-pause", input_pausable_changed, p_mi );
987
    var_AddCallback( p_input_thread, "program-scrambled", input_scrambled_changed, p_mi );
Laurent Aimar's avatar
Laurent Aimar committed
988
    var_AddCallback( p_input_thread, "intf-event", input_event_changed, p_mi );
989
    add_es_callbacks( p_input_thread, p_mi );
990

991 992
    if( input_Start( p_input_thread ) )
    {
993
        unlock_input(p_mi);
994
        del_es_callbacks( p_input_thread, p_mi );
995 996
        var_DelCallback( p_input_thread, "intf-event", input_event_changed, p_mi );
        var_DelCallback( p_input_thread, "can-pause", input_pausable_changed, p_mi );
997
        var_DelCallback( p_input_thread, "program-scrambled", input_scrambled_changed, p_mi );
998
        var_DelCallback( p_input_thread, "can-seek", input_seekable_changed, p_mi );
999
        input_Close( p_input_thread );
1000
        media_detach_preparsed_event( p_mi->p_md );
1001 1002
        libvlc_printerr( "Input initialization failure" );
        return -1;
1003
    }
1004 1005
    p_mi->input.p_thread = p_input_thread;
    unlock_input(p_mi);
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
1006
    return 0;
1007 1008
}

1009
void libvlc_media_player_set_pause( libvlc_media_player_t *p_mi, int paused )
1010
{
1011
    input_thread_t * p_input_thread = libvlc_get_input_thread( p_mi );
1012
    if( !p_input_thread )
1013 1014
        return;

1015
    if( paused )
1016
    {
1017 1018 1019 1020
        if( libvlc_media_player_can_pause( p_mi ) )
            input_Control( p_input_thread, INPUT_SET_STATE, PAUSE_S );
        else
            input_Stop( p_input_thread );
1021
    }
1022
    else
1023
    {
1024
        input_Control( p_input_thread, INPUT_SET_STATE, PLAYING_S );
1025
    }
1026

1027
    vlc_object_release( p_input_thread );
1028
}
1029

1030 1031 1032 1033 1034
/**************************************************************************
 * Toggle pause.
 **************************************************************************/
void libvlc_media_player_pause( libvlc_media_player_t *p_mi )
{
1035
    libvlc_media_player_set_pause( p_mi, libvlc_media_player_is_playing( p_mi ) );
1036 1037
}

1038
/**************************************************************************
1039
 * Tells whether the media player is currently playing.
1040
 **************************************************************************/
1041
int libvlc_media_player_is_playing( libvlc_media_player_t *p_mi )
1042
{
1043
    libvlc_state_t state = libvlc_media_player_get_state( p_mi );
1044
    return libvlc_Playing == state;
1045 1046
}

1047
/**************************************************************************
1048
 * Stop playing.
1049
 **************************************************************************/
1050
void libvlc_media_player_stop( libvlc_media_player_t *p_mi )
1051
{
1052
    lock_input(p_mi);
1053
    release_input_thread( p_mi ); /* This will stop the input thread */
1054 1055 1056

    /* Force to go to stopped state, in case we were in Ended, or Error
     * state. */
1057
    if( p_mi->state != libvlc_Stopped )
1058
    {
1059
        set_state( p_mi, libvlc_Stopped, false );
1060 1061 1062

        /* Construct and send the event */
        libvlc_event_t event;
1063
        event.type = libvlc_MediaPlayerStopped;
1064
        libvlc_event_send( &p_mi->event_manager, &event );
1065
    }
1066

1067
    input_resource_Terminate( p_mi->input.p_resource );
1068
    unlock_input(p_mi);
1069 1070
}

1071
int libvlc_media_player_set_renderer( libvlc_media_player_t *p_mi,
1072
                                      libvlc_renderer_item_t *p_litem )
1073
{
1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085
    vlc_renderer_item_t *p_item =
        p_litem ? libvlc_renderer_item_to_vlc( p_litem ) : NULL;

    lock_input( p_mi );
    input_thread_t *p_input_thread = p_mi->input.p_thread;
    if( p_input_thread )
        input_Control( p_input_thread, INPUT_SET_RENDERER, p_item );

    if( p_mi->input.p_renderer )
        vlc_renderer_item_release( p_mi->input.p_renderer );
    p_mi->input.p_renderer = p_item ? vlc_renderer_item_hold( p_item ) : NULL;
    unlock_input( p_mi );
1086 1087 1088

    return 0;
}
1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099

void libvlc_video_set_callbacks( libvlc_media_player_t *mp,
    void *(*lock_cb) (void *, void **),
    void (*unlock_cb) (void *, void *, void *const *),
    void (*display_cb) (void *, void *),
    void *opaque )
{
    var_SetAddress( mp, "vmem-lock", lock_cb );
    var_SetAddress( mp, "vmem-unlock", unlock_cb );
    var_SetAddress( mp, "vmem-display", display_cb );
    var_SetAddress( mp, "vmem-data", opaque );
1100
    var_SetString( mp, "avcodec-hw", "none" );
1101 1102
    var_SetString( mp, "vout", "vmem" );
    var_SetString( mp, "window", "none" );
1103 1104
}

1105 1106 1107 1108 1109 1110 1111 1112
void libvlc_video_set_format_callbacks( libvlc_media_player_t *mp,
                                        libvlc_video_format_cb setup,
                                        libvlc_video_cleanup_cb cleanup )
{
    var_SetAddress( mp, "vmem-setup", setup );
    var_SetAddress( mp, "vmem-cleanup", cleanup );
}

1113 1114 1115 1116 1117 1118 1119 1120 1121
void libvlc_video_set_format( libvlc_media_player_t *mp, const char *chroma,
                              unsigned width, unsigned height, unsigned pitch )
{
    var_SetString( mp, "vmem-chroma", chroma );
    var_SetInteger( mp, "vmem-width", width );
    var_SetInteger( mp, "vmem-height", height );
    var_SetInteger( mp, "vmem-pitch", pitch );
}

1122 1123 1124 1125
/**************************************************************************
 * set_nsobject
 **************************************************************************/
void libvlc_media_player_set_nsobject( libvlc_media_player_t *p_mi,
1126
                                        void * drawable )
1127
{
1128 1129
    assert (p_mi != NULL);
#ifdef __APPLE__
1130 1131 1132
    var_SetString (p_mi, "avcodec-hw", "");
    var_SetString (p_mi, "vout", "");
    var_SetString (p_mi, "window", "");
1133 1134
    var_SetAddress (p_mi, "drawable-nsobject", drawable);
#else
1135 1136 1137 1138 1139
    (void)drawable;
    libvlc_printerr ("can't set nsobject: APPLE build required");
    assert(false);
    var_SetString (p_mi, "vout", "none");
    var_SetString (p_mi, "window", "none");
1140
#endif
1141 1142 1143
}

/**************************************************************************
1144
 * get_nsobject
1145
 **************************************************************************/
Pierre's avatar
Pierre committed
1146
void * libvlc_media_player_get_nsobject( libvlc_media_player_t *p_mi )
1147
{
1148 1149 1150 1151
    assert (p_mi != NULL);
#ifdef __APPLE__
    return var_GetAddress (p_mi, "drawable-nsobject");
#else
1152
    (void) p_mi;
1153 1154
    return NULL;
#endif
1155 1156
}

1157 1158 1159 1160
/**************************************************************************
 * set_agl
 **************************************************************************/
void libvlc_media_player_set_agl( libvlc_media_player_t *p_mi,
1161
                                  uint32_t drawable )
1162
{
1163 1164 1165 1166 1167
    (void)drawable;
    libvlc_printerr ("can't set agl: use libvlc_media_player_set_nsobject instead");
    assert(false);
    var_SetString (p_mi, "vout", "none");
    var_SetString (p_mi, "window", "none");
1168 1169 1170 1171 1172 1173 1174
}

/**************************************************************************
 * get_agl
 **************************************************************************/
uint32_t libvlc_media_player_get_agl( libvlc_media_player_t *p_mi )
{
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
1175
    (void) p_mi;
1176
    return 0;
1177 1178
}

1179 1180 1181
/**************************************************************************
 * set_xwindow
 **************************************************************************/
1182
void libvlc_media_player_set_xwindow( libvlc_media_player_t *p_mi,
1183
                                      uint32_t drawable )
1184
{
1185
    assert (p_mi != NULL);
1186

Rémi Denis-Courmont's avatar