media_player.c 66.2 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
#include <vlc_http.h>
40 41 42 43

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

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

48
static int
49 50 51 52 53 54 55 56
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
57 58 59 60
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
61
input_event_changed( vlc_object_t * p_this, char const * psz_cmd,
62 63 64
                     vlc_value_t oldval, vlc_value_t newval,
                     void * p_userdata );

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

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

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

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

82 83 84 85 86 87
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 );

88 89 90
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 );
91

92
static void libvlc_media_player_destroy( libvlc_media_player_t *p_mi );
93

94 95 96 97
/*
 * Shortcuts
 */

98 99 100 101 102 103 104 105 106
/*
 * 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.
 */
107 108 109 110 111 112 113 114 115 116
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);
}

117 118 119 120 121 122 123 124 125 126
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);
}

127 128 129 130 131 132 133 134 135 136
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;
137
        libvlc_event_send( &p_md->event_manager, &event );
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
    }
}

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

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

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

171 172
    media_detach_preparsed_event( p_mi->p_md );

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

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

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

196
    assert( p_mi );
197

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

206 207 208
    return p_input_thread;
}

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

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

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

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

        libvlc_media_release(media);
235 236 237
    }
}

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

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

252
    libvlc_event_send( &p_mi->event_manager, &event );
253 254 255 256 257 258 259 260 261
    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);
262 263
    VLC_UNUSED(p_this);
    VLC_UNUSED(psz_cmd);
264
    libvlc_media_player_t * p_mi = p_userdata;
265 266
    libvlc_event_t event;

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

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

274 275 276 277 278 279 280 281 282 283 284 285 286 287
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;

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

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

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

304 305
    if( newval.i_int == INPUT_EVENT_STATE )
    {
306
        libvlc_state_t libvlc_state;
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 337

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

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

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

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

        /* */
        event.type = libvlc_MediaPlayerTimeChanged;
363
        event.u.media_player_time_changed.new_time =
364
           from_mtime(var_GetInteger( p_input, "time" ));
365
        libvlc_event_send( &p_mi->event_manager, &event );
366
    }
367 368 369 370
    else if( newval.i_int == INPUT_EVENT_LENGTH )
    {
        event.type = libvlc_MediaPlayerLengthChanged;
        event.u.media_player_length_changed.new_length =
371
           from_mtime(var_GetInteger( p_input, "length" ));
372
        libvlc_event_send( &p_mi->event_manager, &event );
373
    }
374 375 376
    else if( newval.i_int == INPUT_EVENT_CACHE )
    {
        event.type = libvlc_MediaPlayerBuffering;
377
        event.u.media_player_buffering.new_cache = (100 *
378
            var_GetFloat( p_input, "cache" ));
379
        libvlc_event_send( &p_mi->event_manager, &event );
380
    }
381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397
    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;
398
        libvlc_event_send( &p_mi->event_manager, &event );
399
    }
400 401 402 403
    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" );
404
        libvlc_event_send( &p_mi->event_manager, &event );
405
    }
406 407 408 409
    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" );
410
        libvlc_event_send( &p_mi->event_manager, &event );
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 444
    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;
445
                libvlc_event_send( &p_mi->event_manager, &event );
446 447 448
            }
        }
    }
Laurent Aimar's avatar
Laurent Aimar committed
449

450 451 452
    return VLC_SUCCESS;
}

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 507
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;

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

    return VLC_SUCCESS;
}

513 514 515 516 517 518 519 520 521 522 523 524 525 526
/**************************************************************************
 * 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;
527
    libvlc_event_send(&mp->event_manager, &event);
528 529 530 531

    return VLC_SUCCESS;
}

532 533 534 535 536 537 538 539 540 541 542
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;
543
        libvlc_event_send(&mp->event_manager, &event);
544 545 546 547 548
    }
    VLC_UNUSED(name); VLC_UNUSED(opaque);
    return VLC_SUCCESS;
}

549 550 551 552 553 554 555 556
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;
557
    libvlc_event_send(&mp->event_manager, &event);
558 559 560 561
    VLC_UNUSED(name); VLC_UNUSED(old); VLC_UNUSED(opaque);
    return VLC_SUCCESS;
}

562 563 564 565 566 567 568 569 570 571 572
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;
573
        libvlc_event_send(&mp->event_manager, &event);
574 575 576 577 578
    }
    VLC_UNUSED(name); VLC_UNUSED(opaque);
    return VLC_SUCCESS;
}

579 580 581 582 583 584 585 586
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;
587
    libvlc_event_send(&mp->event_manager, &event);
588 589 590 591
    VLC_UNUSED(name); VLC_UNUSED(old); VLC_UNUSED(opaque);
    return VLC_SUCCESS;
}

592
/**************************************************************************
593 594 595 596 597 598 599 600 601 602 603 604
 * 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.
605
 **************************************************************************/
606
libvlc_media_player_t *
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
607
libvlc_media_player_new( libvlc_instance_t *instance )
608
{
609
    libvlc_media_player_t * mp;
610

611
    assert(instance);
612

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

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

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

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

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

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

669 670 671 672
    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);

673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690
    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);

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

697
     /* Audio */
698
    var_Create (mp, "aout", VLC_VAR_STRING | VLC_VAR_DOINHERIT);
699
    var_Create (mp, "audio-device", VLC_VAR_STRING);
700
    var_Create (mp, "mute", VLC_VAR_BOOL);
701
    var_Create (mp, "volume", VLC_VAR_FLOAT);
702
    var_Create (mp, "corks", VLC_VAR_INTEGER);
703
    var_Create (mp, "audio-filter", VLC_VAR_STRING);
704
    var_Create (mp, "role", VLC_VAR_STRING | VLC_VAR_DOINHERIT);
705 706
    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
707
    var_Create (mp, "amem-cleanup", VLC_VAR_ADDRESS);
708
    var_Create (mp, "amem-play", VLC_VAR_ADDRESS);
709 710 711 712
    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);
713 714 715 716
    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);
717

718 719 720 721 722
    /* 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
723 724
    /* Equalizer */
    var_Create (mp, "equalizer-preamp", VLC_VAR_FLOAT);
725
    var_Create (mp, "equalizer-vlcfreqs", VLC_VAR_BOOL);
Mark Lee's avatar
Mark Lee committed
726 727
    var_Create (mp, "equalizer-bands", VLC_VAR_STRING);

728 729 730 731 732 733 734 735 736
    /* Initialize the shared HTTP cookie jar */
    vlc_value_t cookies;
    cookies.p_address = vlc_http_cookies_new();
    if ( likely(cookies.p_address) )
    {
        var_Create(mp, "http-cookies", VLC_VAR_ADDRESS);
        var_SetChecked(mp, "http-cookies", VLC_VAR_ADDRESS, cookies);
    }

737
    mp->p_md = NULL;
738
    mp->state = libvlc_NothingSpecial;
739
    mp->p_libvlc_instance = instance;
740
    mp->input.p_thread = NULL;
741
    mp->input.p_renderer = NULL;
742 743 744 745 746 747
    mp->input.p_resource = input_resource_New(VLC_OBJECT(mp));
    if (unlikely(mp->input.p_resource == NULL))
    {
        vlc_object_release(mp);
        return NULL;
    }
748 749 750 751
    audio_output_t *aout = input_resource_GetAout(mp->input.p_resource);
    if( aout != NULL )
        input_resource_PutAout(mp->input.p_resource, aout);

752 753 754 755
    vlc_viewpoint_init(&mp->viewpoint);

    var_Create (mp, "viewpoint", VLC_VAR_ADDRESS);
    var_SetAddress( mp, "viewpoint", &mp->viewpoint );
756
    vlc_mutex_init (&mp->input.lock);
757
    mp->i_refcount = 1;
758
    libvlc_event_manager_init(&mp->event_manager, mp);
759
    vlc_mutex_init(&mp->object_lock);
760

761
    var_AddCallback(mp, "corks", corks_changed, NULL);
762
    var_AddCallback(mp, "audio-device", audio_device_changed, NULL);
763
    var_AddCallback(mp, "mute", mute_changed, NULL);
764
    var_AddCallback(mp, "volume", volume_changed, NULL);
765

766 767
    /* Snapshot initialization */
    /* Attach a var callback to the global object to provide the glue between
768 769 770 771 772 773
     * 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.
     */
774
    var_AddCallback(mp->obj.libvlc, "snapshot-file", snapshot_was_taken, mp);
775

776
    libvlc_retain(instance);
777
    return mp;
778 779 780
}

/**************************************************************************
781
 * Create a Media Instance object with a media descriptor.
782
 **************************************************************************/
783
libvlc_media_player_t *
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
784
libvlc_media_player_new_from_media( libvlc_media_t * p_md )
785
{
786
    libvlc_media_player_t * p_mi;
787

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
788
    p_mi = libvlc_media_player_new( p_md->p_libvlc_instance );
789
    if( !p_mi )
790 791
        return NULL;

792
    libvlc_media_retain( p_md );
793
    p_mi->p_md = p_md;
794 795 796 797 798

    return p_mi;
}

/**************************************************************************
799
 * Destroy a Media Instance object (libvlc internal)
800
 *
801
 * Warning: No lock held here, but hey, this is internal. Caller must lock.
802
 **************************************************************************/
803
static void libvlc_media_player_destroy( libvlc_media_player_t *p_mi )
804
{
805
    assert( p_mi );
806

807
    /* Detach Callback from the main libvlc object */
808
    var_DelCallback( p_mi->obj.libvlc,
809
                     "snapshot-file", snapshot_was_taken, p_mi );
810

811
    /* Detach callback from the media player / input manager object */
812
    var_DelCallback( p_mi, "volume", volume_changed, NULL );
813
    var_DelCallback( p_mi, "mute", mute_changed, NULL );
814
    var_DelCallback( p_mi, "audio-device", audio_device_changed, NULL );
815 816
    var_DelCallback( p_mi, "corks", corks_changed, NULL );

817 818
    /* No need for lock_input() because no other threads knows us anymore */
    if( p_mi->input.p_thread )
819
        release_input_thread(p_mi);
820 821
    input_resource_Terminate( p_mi->input.p_resource );
    input_resource_Release( p_mi->input.p_resource );
822 823 824
    if( p_mi->input.p_renderer )
        vlc_renderer_item_release( p_mi->input.p_renderer );

825
    vlc_mutex_destroy( &p_mi->input.lock );
826

827
    libvlc_event_manager_destroy(&p_mi->event_manager);
828
    libvlc_media_release( p_mi->p_md );
829
    vlc_mutex_destroy( &p_mi->object_lock );
830

831 832 833 834 835 836 837
    vlc_http_cookie_jar_t *cookies = var_GetAddress( p_mi, "http-cookies" );
    if ( cookies )
    {
        var_Destroy( p_mi, "http-cookies" );
        vlc_http_cookies_destroy( cookies );
    }

838
    libvlc_instance_t *instance = p_mi->p_libvlc_instance;
839
    vlc_object_release( p_mi );
840
    libvlc_release(instance);
841 842 843
}

/**************************************************************************
844 845 846
 * Release a Media Instance object.
 *
 * Function does the locking.
847
 **************************************************************************/
848
void libvlc_media_player_release( libvlc_media_player_t *p_mi )
849
{
850
    bool destroy;
851

852
    assert( p_mi );
853
    lock(p_mi);
854
    destroy = !--p_mi->i_refcount;
855
    unlock(p_mi);
856

857 858
    if( destroy )
        libvlc_media_player_destroy( p_mi );
859
}
860

861
/**************************************************************************
862 863 864
 * Retain a Media Instance object.
 *
 * Caller must hold the lock.
865
 **************************************************************************/
866
void libvlc_media_player_retain( libvlc_media_player_t *p_mi )
867
{
868
    assert( p_mi );
869

870
    lock(p_mi);
871
    p_mi->i_refcount++;
872
    unlock(p_mi);
873
}
874

875
/**************************************************************************
876 877 878
 * Set the Media descriptor associated with the instance.
 *
 * Enter without lock -- function will lock the object.
879
 **************************************************************************/
880 881
void libvlc_media_player_set_media(
                            libvlc_media_player_t *p_mi,
882
                            libvlc_media_t *p_md )
883
{
884
    lock_input(p_mi);
885

886
    release_input_thread( p_mi );
887

888
    lock( p_mi );
889
    set_state( p_mi, libvlc_NothingSpecial, true );
890
    unlock_input( p_mi );
891

892
    libvlc_media_release( p_mi->p_md );
893

894 895 896
    if( !p_md )
    {
        p_mi->p_md = NULL;
897
        unlock(p_mi);
898 899 900
        return; /* It is ok to pass a NULL md */
    }

901
    libvlc_media_retain( p_md );
902
    p_mi->p_md = p_md;
903

904 905 906 907
    /* 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;

908
    unlock(p_mi);
909 910 911 912 913

    /* 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;
914
    libvlc_event_send( &p_mi->event_manager, &event );
915

916 917 918
}

/**************************************************************************
919
 * Get the Media descriptor associated with the instance.
920
 **************************************************************************/
921
libvlc_media_t *
922
libvlc_media_player_get_media( libvlc_media_player_t *p_mi )
923
{
924
    libvlc_media_t *p_m;
925

926
    lock( p_mi );
927 928
    p_m = p_mi->p_md;
    if( p_m )
929 930 931 932
        libvlc_media_retain( p_m );
    unlock( p_mi );

    return p_m;
933 934
}

935
/**************************************************************************
936
 * Get the event Manager.
937 938
 **************************************************************************/
libvlc_event_manager_t *
939
libvlc_media_player_event_manager( libvlc_media_player_t *p_mi )
940
{
941
    return &p_mi->event_manager;
942 943
}

944 945 946 947 948 949 950 951 952 953 954 955 956 957
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 );
}

958
/**************************************************************************
959
 * Tell media player to start playing.
960
 **************************************************************************/
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
961
int libvlc_media_player_play( libvlc_media_player_t *p_mi )
962
{
963
    lock_input( p_mi );
964

965 966
    input_thread_t *p_input_thread = p_mi->input.p_thread;
    if( p_input_thread )
967
    {
Sam Hocevar's avatar
Sam Hocevar committed
968
        /* A thread already exists, send it a play message */
969
        input_Control( p_input_thread, INPUT_SET_STATE, PLAYING_S );
970
        unlock_input( p_mi );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
971
        return 0;
972 973
    }

974
    /* Ignore previous exception */
975
    lock(p_mi);
976

977 978
    if( !p_mi->p_md )
    {
979
        unlock(p_mi);
980
        unlock_input( p_mi );
981
        libvlc_printerr( "No associated media descriptor" );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
982
        return -1;
983 984
    }

985 986 987
    for( size_t i = 0; i < ARRAY_SIZE( p_mi->selected_es ); ++i )
        p_mi->selected_es[i] = ES_INIT;

988 989
    media_attach_preparsed_event( p_mi->p_md );

990
    p_input_thread = input_Create( p_mi, p_mi->p_md->p_input_item, NULL,
991 992
                                   p_mi->input.p_resource,
                                   p_mi->input.p_renderer );
993 994
    unlock(p_mi);
    if( !p_input_thread )
995
    {
996
        unlock_input(p_mi);
997
        media_detach_preparsed_event( p_mi->p_md );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
998 999
        libvlc_printerr( "Not enough memory" );
        return -1;
1000
    }
1001

1002 1003
    var_AddCallback( p_input_thread, "can-seek", input_seekable_changed, p_mi );
    var_AddCallback( p_input_thread, "can-pause", input_pausable_changed, p_mi );
1004
    var_AddCallback( p_input_thread, "program-scrambled", input_scrambled_changed, p_mi );
Laurent Aimar's avatar
Laurent Aimar committed
1005
    var_AddCallback( p_input_thread, "intf-event", input_event_changed, p_mi );
1006
    add_es_callbacks( p_input_thread, p_mi );
1007

1008 1009
    if( input_Start( p_input_thread ) )
    {
1010
        unlock_input(p_mi);
1011
        del_es_callbacks( p_input_thread, p_mi );
1012 1013
        var_DelCallback( p_input_thread, "intf-event", input_event_changed, p_mi );
        var_DelCallback( p_input_thread, "can-pause", input_pausable_changed, p_mi );
1014
        var_DelCallback( p_input_thread, "program-scrambled", input_scrambled_changed, p_mi );
1015
        var_DelCallback( p_input_thread, "can-seek", input_seekable_changed, p_mi );
1016
        input_Close( p_input_thread );
1017
        media_detach_preparsed_event( p_mi->p_md );
1018 1019
        libvlc_printerr( "Input initialization failure" );
        return -1;
1020
    }
1021 1022
    p_mi->input.p_thread = p_input_thread;
    unlock_input(p_mi);
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
1023
    return 0;
1024 1025
}

1026
void libvlc_media_player_set_pause( libvlc_media_player_t *p_mi, int paused )
1027
{
1028
    input_thread_t * p_input_thread = libvlc_get_input_thread( p_mi );
1029
    if( !p_input_thread )
1030 1031
        return;

1032
    if( paused )
1033
    {
1034 1035 1036 1037
        if( libvlc_media_player_can_pause( p_mi ) )
            input_Control( p_input_thread, INPUT_SET_STATE, PAUSE_S );
        else
            input_Stop( p_input_thread );
1038
    }
1039
    else
1040
    {
1041
        input_Control( p_input_thread, INPUT_SET_STATE, PLAYING_S );
1042
    }
1043

1044
    vlc_object_release( p_input_thread );
1045
}
1046

1047 1048 1049 1050 1051
/**************************************************************************
 * Toggle pause.
 **************************************************************************/
void libvlc_media_player_pause( libvlc_media_player_t *p_mi )
{
1052
    libvlc_media_player_set_pause( p_mi, libvlc_media_player_is_playing( p_mi ) );
1053 1054
}

1055
/**************************************************************************
1056
 * Tells whether the media player is currently playing.
1057
 **************************************************************************/
1058
int libvlc_media_player_is_playing( libvlc_media_player_t *p_mi )
1059
{
1060
    libvlc_state_t state = libvlc_media_player_get_state( p_mi );
1061
    return libvlc_Playing == state;
1062 1063
}

1064
/**************************************************************************
1065
 * Stop playing.
1066
 **************************************************************************/
1067
void libvlc_media_player_stop( libvlc_media_player_t *p_mi )
1068
{
1069
    lock_input(p_mi);
1070
    release_input_thread( p_mi ); /* This will stop the input thread */
1071 1072 1073

    /* Force to go to stopped state, in case we were in Ended, or Error
     * state. */
1074
    if( p_mi->state != libvlc_Stopped )
1075
    {
1076
        set_state( p_mi, libvlc_Stopped, false );
1077 1078 1079

        /* Construct and send the event */
        libvlc_event_t event;
1080
        event.type = libvlc_MediaPlayerStopped;
1081
        libvlc_event_send( &p_mi->event_manager, &event );
1082
    }
1083

1084
    input_resource_Terminate( p_mi->input.p_resource );
1085
    unlock_input(p_mi);
1086 1087
}

1088
int libvlc_media_player_set_renderer( libvlc_media_player_t *p_mi,
1089
                                      libvlc_renderer_item_t *p_litem )
1090
{
1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102
    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 );
1103 1104 1105

    return 0;
}
1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116

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 );
1117
    var_SetString( mp, "avcodec-hw", "none" );
1118 1119
    var_SetString( mp, "vout", "vmem" );
    var_SetString( mp, "window", "none" );
1120 1121
}

1122 1123 1124 1125 1126 1127 1128 1129
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 );
}

1130 1131 1132 1133 1134 1135 1136 1137 1138
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 );
}

1139 1140 1141 1142
/**************************************************************************
 * set_nsobject
 **************************************************************************/
void libvlc_media_player_set_nsobject( libvlc_media_player_t *p_mi,
1143
                                        void * drawable )
1144
{
1145 1146
    assert (p_mi != NULL);
#ifdef __APPLE__
1147 1148 1149
    var_SetString (p_mi, "avcodec-hw", "");
    var_SetString (p_mi, "vout", "");
    var_SetString (p_mi, "window", "");
1150 1151
    var_SetAddress (p_mi, "drawable-nsobject", drawable);
#else
1152 1153 1154 1155 1156
    (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");
1157
#endif
1158 1159 1160
}

/**************************************************************************
1161
 * get_nsobject
1162
 **************************************************************************/
Pierre's avatar
Pierre committed
1163
void * libvlc_media_player_get_nsobject( libvlc_media_player_t *p_mi )
1164
{
1165 1166 1167 1168
    assert (p_mi != NULL);
#ifdef __APPLE__
    return var_GetAddress (p_mi, "drawable-nsobject");
#else
1169
    (void) p_mi;
1170 1171
    return NULL;
#endif
1172 1173
}

1174 1175 1176 1177
/**************************************************************************
 * set_agl
 **************************************************************************/
void libvlc_media_player_set_agl( libvlc_media_player_t *p_mi,
1178
                                  uint32_t drawable )
1179
{
1180 1181 1182 1183 1184
    (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");
1185 1186 1187 1188 1189 1190 1191
}

/**************************************************************************
 * 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
1192
    (void) p_mi;
1193
    return 0;
1194 1195