contrib:tiger: update libtiger to 0.3.4
[vlc.git] / lib / media_player.c
blob58b2de9d8085f56503ebd53a1fe12e5d878015a9
1 /*****************************************************************************
2 * media_player.c: Libvlc API Media Instance management functions
3 *****************************************************************************
4 * Copyright (C) 2005-2015 VLC authors and VideoLAN
6 * Authors: Clément Stenac <zorglub@videolan.org>
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation; either version 2.1 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
23 #ifdef HAVE_CONFIG_H
24 # include "config.h"
25 #endif
27 #include <assert.h>
29 #include <vlc/libvlc.h>
30 #include <vlc/libvlc_media.h>
31 #include <vlc/libvlc_events.h>
33 #include <vlc_demux.h>
34 #include <vlc_input.h>
35 #include <vlc_vout.h>
36 #include <vlc_aout.h>
37 #include <vlc_keys.h>
39 #include "libvlc_internal.h"
40 #include "media_internal.h" // libvlc_media_set_state()
41 #include "media_player_internal.h"
43 static int
44 input_seekable_changed( vlc_object_t * p_this, char const * psz_cmd,
45 vlc_value_t oldval, vlc_value_t newval,
46 void * p_userdata );
47 static int
48 input_pausable_changed( vlc_object_t * p_this, char const * psz_cmd,
49 vlc_value_t oldval, vlc_value_t newval,
50 void * p_userdata );
51 static int
52 input_scrambled_changed( vlc_object_t * p_this, char const * psz_cmd,
53 vlc_value_t oldval, vlc_value_t newval,
54 void * p_userdata );
55 static int
56 input_event_changed( vlc_object_t * p_this, char const * psz_cmd,
57 vlc_value_t oldval, vlc_value_t newval,
58 void * p_userdata );
60 static int
61 input_es_changed( vlc_object_t * p_this, char const * psz_cmd,
62 int action, vlc_value_t *p_val,
63 void *p_userdata);
65 static int
66 input_es_selected( vlc_object_t * p_this, char const * psz_cmd,
67 vlc_value_t oldval, vlc_value_t newval,
68 void * p_userdata );
70 static int
71 corks_changed(vlc_object_t *obj, const char *name, vlc_value_t old,
72 vlc_value_t cur, void *opaque);
74 static int
75 mute_changed(vlc_object_t *obj, const char *name, vlc_value_t old,
76 vlc_value_t cur, void *opaque);
78 static int
79 volume_changed(vlc_object_t *obj, const char *name, vlc_value_t old,
80 vlc_value_t cur, void *opaque);
82 static void
83 add_es_callbacks( input_thread_t *p_input_thread, libvlc_media_player_t *p_mi );
85 static void
86 del_es_callbacks( input_thread_t *p_input_thread, libvlc_media_player_t *p_mi );
88 static int
89 snapshot_was_taken( vlc_object_t *p_this, char const *psz_cmd,
90 vlc_value_t oldval, vlc_value_t newval, void *p_data );
92 static void libvlc_media_player_destroy( libvlc_media_player_t *p_mi );
95 * Shortcuts
99 * The input lock protects the input and input resource pointer.
100 * It MUST NOT be used from callbacks.
102 * The object lock protects the reset, namely the media and the player state.
103 * It can, and usually needs to be taken from callbacks.
104 * The object lock can be acquired under the input lock... and consequently
105 * the opposite order is STRICTLY PROHIBITED.
107 static inline void lock(libvlc_media_player_t *mp)
109 vlc_mutex_lock(&mp->object_lock);
112 static inline void unlock(libvlc_media_player_t *mp)
114 vlc_mutex_unlock(&mp->object_lock);
117 static inline void lock_input(libvlc_media_player_t *mp)
119 vlc_mutex_lock(&mp->input.lock);
122 static inline void unlock_input(libvlc_media_player_t *mp)
124 vlc_mutex_unlock(&mp->input.lock);
128 * Release the associated input thread.
130 * Object lock is NOT held.
131 * Input lock is held or instance is being destroyed.
133 static void release_input_thread( libvlc_media_player_t *p_mi )
135 assert( p_mi );
137 input_thread_t *p_input_thread = p_mi->input.p_thread;
138 if( !p_input_thread )
139 return;
140 p_mi->input.p_thread = NULL;
142 var_DelCallback( p_input_thread, "can-seek",
143 input_seekable_changed, p_mi );
144 var_DelCallback( p_input_thread, "can-pause",
145 input_pausable_changed, p_mi );
146 var_DelCallback( p_input_thread, "program-scrambled",
147 input_scrambled_changed, p_mi );
148 var_DelCallback( p_input_thread, "intf-event",
149 input_event_changed, p_mi );
150 del_es_callbacks( p_input_thread, p_mi );
152 /* We owned this one */
153 input_Stop( p_input_thread );
154 input_Close( p_input_thread );
158 * Retrieve the input thread. Be sure to release the object
159 * once you are done with it. (libvlc Internal)
161 input_thread_t *libvlc_get_input_thread( libvlc_media_player_t *p_mi )
163 input_thread_t *p_input_thread;
165 assert( p_mi );
167 lock_input(p_mi);
168 p_input_thread = p_mi->input.p_thread;
169 if( p_input_thread )
170 vlc_object_hold( p_input_thread );
171 else
172 libvlc_printerr( "No active input" );
173 unlock_input(p_mi);
175 return p_input_thread;
179 * Set the internal state of the media_player. (media player Internal)
181 * Function will lock the media_player.
183 static void set_state( libvlc_media_player_t *p_mi, libvlc_state_t state,
184 bool b_locked )
186 if(!b_locked)
187 lock(p_mi);
188 p_mi->state = state;
190 libvlc_media_t *media = p_mi->p_md;
191 if (media)
192 libvlc_media_retain(media);
194 if(!b_locked)
195 unlock(p_mi);
197 if (media)
199 // Also set the state of the corresponding media
200 // This is strictly for convenience.
201 libvlc_media_set_state(media, state);
203 libvlc_media_release(media);
207 static int
208 input_seekable_changed( vlc_object_t * p_this, char const * psz_cmd,
209 vlc_value_t oldval, vlc_value_t newval,
210 void * p_userdata )
212 VLC_UNUSED(oldval);
213 VLC_UNUSED(p_this);
214 VLC_UNUSED(psz_cmd);
215 libvlc_media_player_t * p_mi = p_userdata;
216 libvlc_event_t event;
218 event.type = libvlc_MediaPlayerSeekableChanged;
219 event.u.media_player_seekable_changed.new_seekable = newval.b_bool;
221 libvlc_event_send( p_mi->p_event_manager, &event );
222 return VLC_SUCCESS;
225 static int
226 input_pausable_changed( vlc_object_t * p_this, char const * psz_cmd,
227 vlc_value_t oldval, vlc_value_t newval,
228 void * p_userdata )
230 VLC_UNUSED(oldval);
231 VLC_UNUSED(p_this);
232 VLC_UNUSED(psz_cmd);
233 libvlc_media_player_t * p_mi = p_userdata;
234 libvlc_event_t event;
236 event.type = libvlc_MediaPlayerPausableChanged;
237 event.u.media_player_pausable_changed.new_pausable = newval.b_bool;
239 libvlc_event_send( p_mi->p_event_manager, &event );
240 return VLC_SUCCESS;
243 static int
244 input_scrambled_changed( vlc_object_t * p_this, char const * psz_cmd,
245 vlc_value_t oldval, vlc_value_t newval,
246 void * p_userdata )
248 VLC_UNUSED(oldval);
249 VLC_UNUSED(p_this);
250 VLC_UNUSED(psz_cmd);
251 libvlc_media_player_t * p_mi = p_userdata;
252 libvlc_event_t event;
254 event.type = libvlc_MediaPlayerScrambledChanged;
255 event.u.media_player_scrambled_changed.new_scrambled = newval.b_bool;
257 libvlc_event_send( p_mi->p_event_manager, &event );
258 return VLC_SUCCESS;
261 static int
262 input_event_changed( vlc_object_t * p_this, char const * psz_cmd,
263 vlc_value_t oldval, vlc_value_t newval,
264 void * p_userdata )
266 VLC_UNUSED(oldval); VLC_UNUSED(psz_cmd);
267 input_thread_t * p_input = (input_thread_t *)p_this;
268 libvlc_media_player_t * p_mi = p_userdata;
269 libvlc_event_t event;
271 assert( !strcmp( psz_cmd, "intf-event" ) );
273 if( newval.i_int == INPUT_EVENT_STATE )
275 libvlc_state_t libvlc_state;
277 switch ( var_GetInteger( p_input, "state" ) )
279 case INIT_S:
280 libvlc_state = libvlc_NothingSpecial;
281 event.type = libvlc_MediaPlayerNothingSpecial;
282 break;
283 case OPENING_S:
284 libvlc_state = libvlc_Opening;
285 event.type = libvlc_MediaPlayerOpening;
286 break;
287 case PLAYING_S:
288 libvlc_state = libvlc_Playing;
289 event.type = libvlc_MediaPlayerPlaying;
290 break;
291 case PAUSE_S:
292 libvlc_state = libvlc_Paused;
293 event.type = libvlc_MediaPlayerPaused;
294 break;
295 case END_S:
296 libvlc_state = libvlc_Ended;
297 event.type = libvlc_MediaPlayerEndReached;
298 break;
299 case ERROR_S:
300 libvlc_state = libvlc_Error;
301 event.type = libvlc_MediaPlayerEncounteredError;
302 break;
304 default:
305 return VLC_SUCCESS;
308 set_state( p_mi, libvlc_state, false );
309 libvlc_event_send( p_mi->p_event_manager, &event );
311 else if( newval.i_int == INPUT_EVENT_DEAD )
313 libvlc_state_t libvlc_state = libvlc_Ended;
314 event.type = libvlc_MediaPlayerStopped;
316 set_state( p_mi, libvlc_state, false );
317 libvlc_event_send( p_mi->p_event_manager, &event );
319 else if( newval.i_int == INPUT_EVENT_POSITION )
321 if( var_GetInteger( p_input, "state" ) != PLAYING_S )
322 return VLC_SUCCESS; /* Don't send the position while stopped */
324 /* */
325 event.type = libvlc_MediaPlayerPositionChanged;
326 event.u.media_player_position_changed.new_position =
327 var_GetFloat( p_input, "position" );
328 libvlc_event_send( p_mi->p_event_manager, &event );
330 /* */
331 event.type = libvlc_MediaPlayerTimeChanged;
332 event.u.media_player_time_changed.new_time =
333 from_mtime(var_GetInteger( p_input, "time" ));
334 libvlc_event_send( p_mi->p_event_manager, &event );
336 else if( newval.i_int == INPUT_EVENT_LENGTH )
338 event.type = libvlc_MediaPlayerLengthChanged;
339 event.u.media_player_length_changed.new_length =
340 from_mtime(var_GetInteger( p_input, "length" ));
341 libvlc_event_send( p_mi->p_event_manager, &event );
343 else if( newval.i_int == INPUT_EVENT_CACHE )
345 event.type = libvlc_MediaPlayerBuffering;
346 event.u.media_player_buffering.new_cache = (int)(100 *
347 var_GetFloat( p_input, "cache" ));
348 libvlc_event_send( p_mi->p_event_manager, &event );
350 else if( newval.i_int == INPUT_EVENT_VOUT )
352 vout_thread_t **pp_vout;
353 size_t i_vout;
354 if( input_Control( p_input, INPUT_GET_VOUTS, &pp_vout, &i_vout ) )
356 i_vout = 0;
358 else
360 for( size_t i = 0; i < i_vout; i++ )
361 vlc_object_release( pp_vout[i] );
362 free( pp_vout );
365 event.type = libvlc_MediaPlayerVout;
366 event.u.media_player_vout.new_count = i_vout;
367 libvlc_event_send( p_mi->p_event_manager, &event );
369 else if ( newval.i_int == INPUT_EVENT_TITLE )
371 event.type = libvlc_MediaPlayerTitleChanged;
372 event.u.media_player_title_changed.new_title = var_GetInteger( p_input, "title" );
373 libvlc_event_send( p_mi->p_event_manager, &event );
375 else if ( newval.i_int == INPUT_EVENT_CHAPTER )
377 event.type = libvlc_MediaPlayerChapterChanged;
378 event.u.media_player_chapter_changed.new_chapter = var_GetInteger( p_input, "chapter" );
379 libvlc_event_send( p_mi->p_event_manager, &event );
382 return VLC_SUCCESS;
385 static int track_type_from_name(const char *psz_name)
387 if( !strcmp( psz_name, "video-es" ) )
388 return libvlc_track_video;
389 else if( !strcmp( psz_name, "audio-es" ) )
390 return libvlc_track_audio;
391 else if( !strcmp( psz_name, "spu-es" ) )
392 return libvlc_track_text;
393 else
394 return libvlc_track_unknown;
397 static int input_es_changed( vlc_object_t *p_this,
398 char const *psz_cmd,
399 int action,
400 vlc_value_t *p_val,
401 void *p_userdata )
403 VLC_UNUSED(p_this);
404 libvlc_media_player_t *mp = p_userdata;
405 libvlc_event_t event;
407 /* Ignore the "Disable" element */
408 if (p_val && p_val->i_int < 0)
409 return VLC_EGENERIC;
411 switch (action)
413 case VLC_VAR_ADDCHOICE:
414 event.type = libvlc_MediaPlayerESAdded;
415 break;
416 case VLC_VAR_DELCHOICE:
417 case VLC_VAR_CLEARCHOICES:
418 event.type = libvlc_MediaPlayerESDeleted;
419 break;
420 default:
421 return VLC_EGENERIC;
424 event.u.media_player_es_changed.i_type = track_type_from_name(psz_cmd);
426 int i_id;
427 if (action != VLC_VAR_CLEARCHOICES)
429 if (!p_val)
430 return VLC_EGENERIC;
431 i_id = p_val->i_int;
433 else
435 /* -1 means all ES tracks of this type were deleted. */
436 i_id = -1;
438 event.u.media_player_es_changed.i_id = i_id;
440 libvlc_event_send(mp->p_event_manager, &event);
442 return VLC_SUCCESS;
445 static int
446 input_es_selected( vlc_object_t * p_this, char const * psz_cmd,
447 vlc_value_t oldval, vlc_value_t newval,
448 void * p_userdata )
450 VLC_UNUSED(p_this);
451 VLC_UNUSED(oldval);
452 libvlc_media_player_t *mp = p_userdata;
453 libvlc_event_t event;
455 event.type = libvlc_MediaPlayerESSelected;
456 event.u.media_player_es_changed.i_type = track_type_from_name(psz_cmd);
457 event.u.media_player_es_changed.i_id = newval.i_int;
459 libvlc_event_send(mp->p_event_manager, &event);
461 return VLC_SUCCESS;
464 /**************************************************************************
465 * Snapshot Taken Event.
467 * FIXME: This snapshot API interface makes no sense in media_player.
468 *************************************************************************/
469 static int snapshot_was_taken(vlc_object_t *p_this, char const *psz_cmd,
470 vlc_value_t oldval, vlc_value_t newval, void *p_data )
472 VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval); VLC_UNUSED(p_this);
474 libvlc_media_player_t *mp = p_data;
475 libvlc_event_t event;
476 event.type = libvlc_MediaPlayerSnapshotTaken;
477 event.u.media_player_snapshot_taken.psz_filename = newval.psz_string;
478 libvlc_event_send(mp->p_event_manager, &event);
480 return VLC_SUCCESS;
483 static int corks_changed(vlc_object_t *obj, const char *name, vlc_value_t old,
484 vlc_value_t cur, void *opaque)
486 libvlc_media_player_t *mp = (libvlc_media_player_t *)obj;
488 if (!old.i_int != !cur.i_int)
490 libvlc_event_t event;
492 event.type = cur.i_int ? libvlc_MediaPlayerCorked
493 : libvlc_MediaPlayerUncorked;
494 libvlc_event_send(mp->p_event_manager, &event);
496 VLC_UNUSED(name); VLC_UNUSED(opaque);
497 return VLC_SUCCESS;
500 static int audio_device_changed(vlc_object_t *obj, const char *name,
501 vlc_value_t old, vlc_value_t cur, void *opaque)
503 libvlc_media_player_t *mp = (libvlc_media_player_t *)obj;
504 libvlc_event_t event;
506 event.type = libvlc_MediaPlayerAudioDevice;
507 event.u.media_player_audio_device.device = cur.psz_string;
508 libvlc_event_send(mp->p_event_manager, &event);
509 VLC_UNUSED(name); VLC_UNUSED(old); VLC_UNUSED(opaque);
510 return VLC_SUCCESS;
513 static int mute_changed(vlc_object_t *obj, const char *name, vlc_value_t old,
514 vlc_value_t cur, void *opaque)
516 libvlc_media_player_t *mp = (libvlc_media_player_t *)obj;
518 if (old.b_bool != cur.b_bool)
520 libvlc_event_t event;
522 event.type = cur.b_bool ? libvlc_MediaPlayerMuted
523 : libvlc_MediaPlayerUnmuted;
524 libvlc_event_send(mp->p_event_manager, &event);
526 VLC_UNUSED(name); VLC_UNUSED(opaque);
527 return VLC_SUCCESS;
530 static int volume_changed(vlc_object_t *obj, const char *name, vlc_value_t old,
531 vlc_value_t cur, void *opaque)
533 libvlc_media_player_t *mp = (libvlc_media_player_t *)obj;
534 libvlc_event_t event;
536 event.type = libvlc_MediaPlayerAudioVolume;
537 event.u.media_player_audio_volume.volume = cur.f_float;
538 libvlc_event_send(mp->p_event_manager, &event);
539 VLC_UNUSED(name); VLC_UNUSED(old); VLC_UNUSED(opaque);
540 return VLC_SUCCESS;
543 /**************************************************************************
544 * Create a Media Instance object.
546 * Refcount strategy:
547 * - All items created by _new start with a refcount set to 1.
548 * - Accessor _release decrease the refcount by 1, if after that
549 * operation the refcount is 0, the object is destroyed.
550 * - Accessor _retain increase the refcount by 1 (XXX: to implement)
552 * Object locking strategy:
553 * - No lock held while in constructor.
554 * - When accessing any member variable this lock is held. (XXX who locks?)
555 * - When attempting to destroy the object the lock is also held.
556 **************************************************************************/
557 libvlc_media_player_t *
558 libvlc_media_player_new( libvlc_instance_t *instance )
560 libvlc_media_player_t * mp;
562 assert(instance);
564 mp = vlc_object_create (instance->p_libvlc_int, sizeof(*mp));
565 if (unlikely(mp == NULL))
567 libvlc_printerr("Not enough memory");
568 return NULL;
571 /* Input */
572 var_Create (mp, "rate", VLC_VAR_FLOAT|VLC_VAR_DOINHERIT);
574 /* Video */
575 var_Create (mp, "vout", VLC_VAR_STRING|VLC_VAR_DOINHERIT);
576 var_Create (mp, "window", VLC_VAR_STRING);
577 var_Create (mp, "vmem-lock", VLC_VAR_ADDRESS);
578 var_Create (mp, "vmem-unlock", VLC_VAR_ADDRESS);
579 var_Create (mp, "vmem-display", VLC_VAR_ADDRESS);
580 var_Create (mp, "vmem-data", VLC_VAR_ADDRESS);
581 var_Create (mp, "vmem-setup", VLC_VAR_ADDRESS);
582 var_Create (mp, "vmem-cleanup", VLC_VAR_ADDRESS);
583 var_Create (mp, "vmem-chroma", VLC_VAR_STRING | VLC_VAR_DOINHERIT);
584 var_Create (mp, "vmem-width", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
585 var_Create (mp, "vmem-height", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
586 var_Create (mp, "vmem-pitch", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
587 var_Create (mp, "avcodec-hw", VLC_VAR_STRING);
588 var_Create (mp, "drawable-xid", VLC_VAR_INTEGER);
589 #if defined (_WIN32) || defined (__OS2__)
590 var_Create (mp, "drawable-hwnd", VLC_VAR_INTEGER);
591 #endif
592 #ifdef __APPLE__
593 var_Create (mp, "drawable-nsobject", VLC_VAR_ADDRESS);
594 #endif
595 #ifdef __ANDROID__
596 var_Create (mp, "android-jvm", VLC_VAR_ADDRESS);
597 var_Create (mp, "drawable-androidwindow", VLC_VAR_ADDRESS);
598 #endif
599 #ifdef HAVE_EVAS
600 var_Create (mp, "drawable-evasobject", VLC_VAR_ADDRESS);
601 #endif
603 var_Create (mp, "keyboard-events", VLC_VAR_BOOL);
604 var_SetBool (mp, "keyboard-events", true);
605 var_Create (mp, "mouse-events", VLC_VAR_BOOL);
606 var_SetBool (mp, "mouse-events", true);
608 var_Create (mp, "fullscreen", VLC_VAR_BOOL);
609 var_Create (mp, "autoscale", VLC_VAR_BOOL | VLC_VAR_DOINHERIT);
610 var_Create (mp, "zoom", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT);
611 var_Create (mp, "aspect-ratio", VLC_VAR_STRING);
612 var_Create (mp, "crop", VLC_VAR_STRING);
613 var_Create (mp, "deinterlace", VLC_VAR_INTEGER);
614 var_Create (mp, "deinterlace-mode", VLC_VAR_STRING);
616 var_Create (mp, "vbi-page", VLC_VAR_INTEGER);
617 var_SetInteger (mp, "vbi-page", 100);
619 var_Create (mp, "marq-marquee", VLC_VAR_STRING);
620 var_Create (mp, "marq-color", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
621 var_Create (mp, "marq-opacity", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
622 var_Create (mp, "marq-position", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
623 var_Create (mp, "marq-refresh", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
624 var_Create (mp, "marq-size", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
625 var_Create (mp, "marq-timeout", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
626 var_Create (mp, "marq-x", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
627 var_Create (mp, "marq-y", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
629 var_Create (mp, "logo-file", VLC_VAR_STRING);
630 var_Create (mp, "logo-x", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
631 var_Create (mp, "logo-y", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
632 var_Create (mp, "logo-delay", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
633 var_Create (mp, "logo-repeat", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
634 var_Create (mp, "logo-opacity", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
635 var_Create (mp, "logo-position", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
637 var_Create (mp, "contrast", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT);
638 var_Create (mp, "brightness", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT);
639 var_Create (mp, "hue", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT);
640 var_Create (mp, "saturation", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT);
641 var_Create (mp, "gamma", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT);
643 /* Audio */
644 var_Create (mp, "aout", VLC_VAR_STRING | VLC_VAR_DOINHERIT);
645 var_Create (mp, "audio-device", VLC_VAR_STRING);
646 var_Create (mp, "mute", VLC_VAR_BOOL);
647 var_Create (mp, "volume", VLC_VAR_FLOAT);
648 var_Create (mp, "corks", VLC_VAR_INTEGER);
649 var_Create (mp, "audio-filter", VLC_VAR_STRING);
650 var_Create (mp, "amem-data", VLC_VAR_ADDRESS);
651 var_Create (mp, "amem-setup", VLC_VAR_ADDRESS);
652 var_Create (mp, "amem-cleanup", VLC_VAR_ADDRESS);
653 var_Create (mp, "amem-play", VLC_VAR_ADDRESS);
654 var_Create (mp, "amem-pause", VLC_VAR_ADDRESS);
655 var_Create (mp, "amem-resume", VLC_VAR_ADDRESS);
656 var_Create (mp, "amem-flush", VLC_VAR_ADDRESS);
657 var_Create (mp, "amem-drain", VLC_VAR_ADDRESS);
658 var_Create (mp, "amem-set-volume", VLC_VAR_ADDRESS);
659 var_Create (mp, "amem-format", VLC_VAR_STRING | VLC_VAR_DOINHERIT);
660 var_Create (mp, "amem-rate", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
661 var_Create (mp, "amem-channels", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
663 /* Video Title */
664 var_Create (mp, "video-title-show", VLC_VAR_BOOL);
665 var_Create (mp, "video-title-position", VLC_VAR_INTEGER);
666 var_Create (mp, "video-title-timeout", VLC_VAR_INTEGER);
668 /* Equalizer */
669 var_Create (mp, "equalizer-preamp", VLC_VAR_FLOAT);
670 var_Create (mp, "equalizer-vlcfreqs", VLC_VAR_BOOL);
671 var_Create (mp, "equalizer-bands", VLC_VAR_STRING);
673 mp->p_md = NULL;
674 mp->state = libvlc_NothingSpecial;
675 mp->p_libvlc_instance = instance;
676 mp->input.p_thread = NULL;
677 mp->input.p_resource = input_resource_New(VLC_OBJECT(mp));
678 if (unlikely(mp->input.p_resource == NULL))
680 vlc_object_release(mp);
681 return NULL;
683 audio_output_t *aout = input_resource_GetAout(mp->input.p_resource);
684 if( aout != NULL )
685 input_resource_PutAout(mp->input.p_resource, aout);
687 vlc_mutex_init (&mp->input.lock);
688 mp->i_refcount = 1;
689 mp->p_event_manager = libvlc_event_manager_new(mp);
690 if (unlikely(mp->p_event_manager == NULL))
692 input_resource_Release(mp->input.p_resource);
693 vlc_object_release(mp);
694 return NULL;
696 vlc_mutex_init(&mp->object_lock);
698 var_AddCallback(mp, "corks", corks_changed, NULL);
699 var_AddCallback(mp, "audio-device", audio_device_changed, NULL);
700 var_AddCallback(mp, "mute", mute_changed, NULL);
701 var_AddCallback(mp, "volume", volume_changed, NULL);
703 /* Snapshot initialization */
704 /* Attach a var callback to the global object to provide the glue between
705 * vout_thread that generates the event and media_player that re-emits it
706 * with its own event manager
708 * FIXME: It's unclear why we want to put this in public API, and why we
709 * want to expose it in such a limiting and ugly way.
711 var_AddCallback(mp->p_libvlc, "snapshot-file", snapshot_was_taken, mp);
713 libvlc_retain(instance);
714 return mp;
717 /**************************************************************************
718 * Create a Media Instance object with a media descriptor.
719 **************************************************************************/
720 libvlc_media_player_t *
721 libvlc_media_player_new_from_media( libvlc_media_t * p_md )
723 libvlc_media_player_t * p_mi;
725 p_mi = libvlc_media_player_new( p_md->p_libvlc_instance );
726 if( !p_mi )
727 return NULL;
729 libvlc_media_retain( p_md );
730 p_mi->p_md = p_md;
732 return p_mi;
735 /**************************************************************************
736 * Destroy a Media Instance object (libvlc internal)
738 * Warning: No lock held here, but hey, this is internal. Caller must lock.
739 **************************************************************************/
740 static void libvlc_media_player_destroy( libvlc_media_player_t *p_mi )
742 assert( p_mi );
744 /* Detach Callback from the main libvlc object */
745 var_DelCallback( p_mi->p_libvlc,
746 "snapshot-file", snapshot_was_taken, p_mi );
748 /* Detach callback from the media player / input manager object */
749 var_DelCallback( p_mi, "volume", volume_changed, NULL );
750 var_DelCallback( p_mi, "mute", mute_changed, NULL );
751 var_DelCallback( p_mi, "audio-device", audio_device_changed, NULL );
752 var_DelCallback( p_mi, "corks", corks_changed, NULL );
754 /* No need for lock_input() because no other threads knows us anymore */
755 if( p_mi->input.p_thread )
756 release_input_thread(p_mi);
757 input_resource_Terminate( p_mi->input.p_resource );
758 input_resource_Release( p_mi->input.p_resource );
759 vlc_mutex_destroy( &p_mi->input.lock );
761 libvlc_event_manager_release( p_mi->p_event_manager );
762 libvlc_media_release( p_mi->p_md );
763 vlc_mutex_destroy( &p_mi->object_lock );
765 libvlc_instance_t *instance = p_mi->p_libvlc_instance;
766 vlc_object_release( p_mi );
767 libvlc_release(instance);
770 /**************************************************************************
771 * Release a Media Instance object.
773 * Function does the locking.
774 **************************************************************************/
775 void libvlc_media_player_release( libvlc_media_player_t *p_mi )
777 bool destroy;
779 assert( p_mi );
780 lock(p_mi);
781 destroy = !--p_mi->i_refcount;
782 unlock(p_mi);
784 if( destroy )
785 libvlc_media_player_destroy( p_mi );
788 /**************************************************************************
789 * Retain a Media Instance object.
791 * Caller must hold the lock.
792 **************************************************************************/
793 void libvlc_media_player_retain( libvlc_media_player_t *p_mi )
795 assert( p_mi );
797 lock(p_mi);
798 p_mi->i_refcount++;
799 unlock(p_mi);
802 /**************************************************************************
803 * Set the Media descriptor associated with the instance.
805 * Enter without lock -- function will lock the object.
806 **************************************************************************/
807 void libvlc_media_player_set_media(
808 libvlc_media_player_t *p_mi,
809 libvlc_media_t *p_md )
811 lock_input(p_mi);
813 release_input_thread( p_mi );
815 lock( p_mi );
816 set_state( p_mi, libvlc_NothingSpecial, true );
817 unlock_input( p_mi );
819 libvlc_media_release( p_mi->p_md );
821 if( !p_md )
823 p_mi->p_md = NULL;
824 unlock(p_mi);
825 return; /* It is ok to pass a NULL md */
828 libvlc_media_retain( p_md );
829 p_mi->p_md = p_md;
831 /* The policy here is to ignore that we were created using a different
832 * libvlc_instance, because we don't really care */
833 p_mi->p_libvlc_instance = p_md->p_libvlc_instance;
835 unlock(p_mi);
837 /* Send an event for the newly available media */
838 libvlc_event_t event;
839 event.type = libvlc_MediaPlayerMediaChanged;
840 event.u.media_player_media_changed.new_media = p_md;
841 libvlc_event_send( p_mi->p_event_manager, &event );
845 /**************************************************************************
846 * Get the Media descriptor associated with the instance.
847 **************************************************************************/
848 libvlc_media_t *
849 libvlc_media_player_get_media( libvlc_media_player_t *p_mi )
851 libvlc_media_t *p_m;
853 lock( p_mi );
854 p_m = p_mi->p_md;
855 if( p_m )
856 libvlc_media_retain( p_m );
857 unlock( p_mi );
859 return p_m;
862 /**************************************************************************
863 * Get the event Manager.
864 **************************************************************************/
865 libvlc_event_manager_t *
866 libvlc_media_player_event_manager( libvlc_media_player_t *p_mi )
868 return p_mi->p_event_manager;
871 static void add_es_callbacks( input_thread_t *p_input_thread, libvlc_media_player_t *p_mi )
873 var_AddListCallback( p_input_thread, "video-es", input_es_changed, p_mi );
874 var_AddListCallback( p_input_thread, "audio-es", input_es_changed, p_mi );
875 var_AddListCallback( p_input_thread, "spu-es", input_es_changed, p_mi );
876 var_AddCallback( p_input_thread, "video-es", input_es_selected, p_mi );
877 var_AddCallback( p_input_thread, "audio-es", input_es_selected, p_mi );
878 var_AddCallback( p_input_thread, "spu-es", input_es_selected, p_mi );
881 static void del_es_callbacks( input_thread_t *p_input_thread, libvlc_media_player_t *p_mi )
883 var_DelListCallback( p_input_thread, "video-es", input_es_changed, p_mi );
884 var_DelListCallback( p_input_thread, "audio-es", input_es_changed, p_mi );
885 var_DelListCallback( p_input_thread, "spu-es", input_es_changed, p_mi );
886 var_DelCallback( p_input_thread, "video-es", input_es_selected, p_mi );
887 var_DelCallback( p_input_thread, "audio-es", input_es_selected, p_mi );
888 var_DelCallback( p_input_thread, "spu-es", input_es_selected, p_mi );
891 /**************************************************************************
892 * Tell media player to start playing.
893 **************************************************************************/
894 int libvlc_media_player_play( libvlc_media_player_t *p_mi )
896 lock_input( p_mi );
898 input_thread_t *p_input_thread = p_mi->input.p_thread;
899 if( p_input_thread )
901 /* A thread already exists, send it a play message */
902 input_Control( p_input_thread, INPUT_SET_STATE, PLAYING_S );
903 unlock_input( p_mi );
904 return 0;
907 /* Ignore previous exception */
908 lock(p_mi);
910 if( !p_mi->p_md )
912 unlock(p_mi);
913 unlock_input( p_mi );
914 libvlc_printerr( "No associated media descriptor" );
915 return -1;
918 p_input_thread = input_Create( p_mi, p_mi->p_md->p_input_item, NULL,
919 p_mi->input.p_resource );
920 unlock(p_mi);
921 if( !p_input_thread )
923 unlock_input(p_mi);
924 libvlc_printerr( "Not enough memory" );
925 return -1;
928 var_AddCallback( p_input_thread, "can-seek", input_seekable_changed, p_mi );
929 var_AddCallback( p_input_thread, "can-pause", input_pausable_changed, p_mi );
930 var_AddCallback( p_input_thread, "program-scrambled", input_scrambled_changed, p_mi );
931 var_AddCallback( p_input_thread, "intf-event", input_event_changed, p_mi );
932 add_es_callbacks( p_input_thread, p_mi );
934 if( input_Start( p_input_thread ) )
936 unlock_input(p_mi);
937 del_es_callbacks( p_input_thread, p_mi );
938 var_DelCallback( p_input_thread, "intf-event", input_event_changed, p_mi );
939 var_DelCallback( p_input_thread, "can-pause", input_pausable_changed, p_mi );
940 var_DelCallback( p_input_thread, "program-scrambled", input_scrambled_changed, p_mi );
941 var_DelCallback( p_input_thread, "can-seek", input_seekable_changed, p_mi );
942 input_Close( p_input_thread );
943 libvlc_printerr( "Input initialization failure" );
944 return -1;
946 p_mi->input.p_thread = p_input_thread;
947 unlock_input(p_mi);
948 return 0;
951 void libvlc_media_player_set_pause( libvlc_media_player_t *p_mi, int paused )
953 input_thread_t * p_input_thread = libvlc_get_input_thread( p_mi );
954 if( !p_input_thread )
955 return;
957 libvlc_state_t state = libvlc_media_player_get_state( p_mi );
958 if( state == libvlc_Playing || state == libvlc_Buffering )
960 if( paused )
962 if( libvlc_media_player_can_pause( p_mi ) )
963 input_Control( p_input_thread, INPUT_SET_STATE, PAUSE_S );
964 else
965 input_Stop( p_input_thread );
968 else
970 if( !paused )
971 input_Control( p_input_thread, INPUT_SET_STATE, PLAYING_S );
974 vlc_object_release( p_input_thread );
977 /**************************************************************************
978 * Toggle pause.
979 **************************************************************************/
980 void libvlc_media_player_pause( libvlc_media_player_t *p_mi )
982 libvlc_state_t state = libvlc_media_player_get_state( p_mi );
983 bool playing = (state == libvlc_Playing || state == libvlc_Buffering);
985 libvlc_media_player_set_pause( p_mi, playing );
988 /**************************************************************************
989 * Tells whether the media player is currently playing.
991 * Enter with lock held.
992 **************************************************************************/
993 int libvlc_media_player_is_playing( libvlc_media_player_t *p_mi )
995 libvlc_state_t state = libvlc_media_player_get_state( p_mi );
996 return (libvlc_Playing == state) || (libvlc_Buffering == state);
999 /**************************************************************************
1000 * Stop playing.
1001 **************************************************************************/
1002 void libvlc_media_player_stop( libvlc_media_player_t *p_mi )
1004 lock_input(p_mi);
1005 release_input_thread( p_mi ); /* This will stop the input thread */
1007 /* Force to go to stopped state, in case we were in Ended, or Error
1008 * state. */
1009 if( p_mi->state != libvlc_Stopped )
1011 set_state( p_mi, libvlc_Stopped, false );
1013 /* Construct and send the event */
1014 libvlc_event_t event;
1015 event.type = libvlc_MediaPlayerStopped;
1016 libvlc_event_send( p_mi->p_event_manager, &event );
1019 input_resource_Terminate( p_mi->input.p_resource );
1020 unlock_input(p_mi);
1024 void libvlc_video_set_callbacks( libvlc_media_player_t *mp,
1025 void *(*lock_cb) (void *, void **),
1026 void (*unlock_cb) (void *, void *, void *const *),
1027 void (*display_cb) (void *, void *),
1028 void *opaque )
1030 var_SetAddress( mp, "vmem-lock", lock_cb );
1031 var_SetAddress( mp, "vmem-unlock", unlock_cb );
1032 var_SetAddress( mp, "vmem-display", display_cb );
1033 var_SetAddress( mp, "vmem-data", opaque );
1034 var_SetString( mp, "avcodec-hw", "none" );
1035 var_SetString( mp, "vout", "vmem" );
1036 var_SetString( mp, "window", "none" );
1039 void libvlc_video_set_format_callbacks( libvlc_media_player_t *mp,
1040 libvlc_video_format_cb setup,
1041 libvlc_video_cleanup_cb cleanup )
1043 var_SetAddress( mp, "vmem-setup", setup );
1044 var_SetAddress( mp, "vmem-cleanup", cleanup );
1047 void libvlc_video_set_format( libvlc_media_player_t *mp, const char *chroma,
1048 unsigned width, unsigned height, unsigned pitch )
1050 var_SetString( mp, "vmem-chroma", chroma );
1051 var_SetInteger( mp, "vmem-width", width );
1052 var_SetInteger( mp, "vmem-height", height );
1053 var_SetInteger( mp, "vmem-pitch", pitch );
1056 /**************************************************************************
1057 * set_nsobject
1058 **************************************************************************/
1059 void libvlc_media_player_set_nsobject( libvlc_media_player_t *p_mi,
1060 void * drawable )
1062 assert (p_mi != NULL);
1063 #ifdef __APPLE__
1064 var_SetString (p_mi, "avcodec-hw", "");
1065 var_SetString (p_mi, "vout", "");
1066 var_SetString (p_mi, "window", "");
1067 var_SetAddress (p_mi, "drawable-nsobject", drawable);
1068 #else
1069 (void)drawable;
1070 libvlc_printerr ("can't set nsobject: APPLE build required");
1071 assert(false);
1072 var_SetString (p_mi, "vout", "none");
1073 var_SetString (p_mi, "window", "none");
1074 #endif
1077 /**************************************************************************
1078 * get_nsobject
1079 **************************************************************************/
1080 void * libvlc_media_player_get_nsobject( libvlc_media_player_t *p_mi )
1082 assert (p_mi != NULL);
1083 #ifdef __APPLE__
1084 return var_GetAddress (p_mi, "drawable-nsobject");
1085 #else
1086 (void) p_mi;
1087 return NULL;
1088 #endif
1091 /**************************************************************************
1092 * set_agl
1093 **************************************************************************/
1094 void libvlc_media_player_set_agl( libvlc_media_player_t *p_mi,
1095 uint32_t drawable )
1097 (void)drawable;
1098 libvlc_printerr ("can't set agl: use libvlc_media_player_set_nsobject instead");
1099 assert(false);
1100 var_SetString (p_mi, "vout", "none");
1101 var_SetString (p_mi, "window", "none");
1104 /**************************************************************************
1105 * get_agl
1106 **************************************************************************/
1107 uint32_t libvlc_media_player_get_agl( libvlc_media_player_t *p_mi )
1109 (void) p_mi;
1110 return 0;
1113 /**************************************************************************
1114 * set_xwindow
1115 **************************************************************************/
1116 void libvlc_media_player_set_xwindow( libvlc_media_player_t *p_mi,
1117 uint32_t drawable )
1119 assert (p_mi != NULL);
1121 var_SetString (p_mi, "avcodec-hw", "");
1122 var_SetString (p_mi, "vout", drawable ? "xid" : "");
1123 var_SetString (p_mi, "window", drawable ? "embed-xid,any" : "");
1124 var_SetInteger (p_mi, "drawable-xid", drawable);
1127 /**************************************************************************
1128 * get_xwindow
1129 **************************************************************************/
1130 uint32_t libvlc_media_player_get_xwindow( libvlc_media_player_t *p_mi )
1132 return var_GetInteger (p_mi, "drawable-xid");
1135 /**************************************************************************
1136 * set_hwnd
1137 **************************************************************************/
1138 void libvlc_media_player_set_hwnd( libvlc_media_player_t *p_mi,
1139 void *drawable )
1141 assert (p_mi != NULL);
1142 #if defined (_WIN32) || defined (__OS2__)
1143 var_SetString (p_mi, "avcodec-hw", "");
1144 var_SetString (p_mi, "vout", "");
1145 var_SetString (p_mi, "window",
1146 (drawable != NULL) ? "embed-hwnd,any" : "");
1147 var_SetInteger (p_mi, "drawable-hwnd", (uintptr_t)drawable);
1148 #else
1149 (void) drawable;
1150 libvlc_printerr ("can't set nsobject: WIN32 build required");
1151 assert(false);
1152 var_SetString (p_mi, "vout", "none");
1153 var_SetString (p_mi, "window", "none");
1154 #endif
1157 /**************************************************************************
1158 * get_hwnd
1159 **************************************************************************/
1160 void *libvlc_media_player_get_hwnd( libvlc_media_player_t *p_mi )
1162 assert (p_mi != NULL);
1163 #if defined (_WIN32) || defined (__OS2__)
1164 return (void *)(uintptr_t)var_GetInteger (p_mi, "drawable-hwnd");
1165 #else
1166 (void) p_mi;
1167 return NULL;
1168 #endif
1171 /**************************************************************************
1172 * set_android_context
1173 **************************************************************************/
1174 void libvlc_media_player_set_android_context( libvlc_media_player_t *p_mi,
1175 void *p_jvm,
1176 void *p_awindow_handler )
1178 assert (p_mi != NULL);
1179 #ifdef __ANDROID__
1180 var_SetAddress (p_mi, "android-jvm", p_jvm);
1181 var_SetAddress (p_mi, "drawable-androidwindow", p_awindow_handler);
1182 #else
1183 (void) p_jvm; (void) p_awindow_handler;
1184 libvlc_printerr ("can't set android context: ANDROID build required");
1185 assert(false);
1186 var_SetString (p_mi, "vout", "none");
1187 var_SetString (p_mi, "window", "none");
1188 #endif
1191 /**************************************************************************
1192 * set_evas_object
1193 **************************************************************************/
1194 int libvlc_media_player_set_evas_object( libvlc_media_player_t *p_mi,
1195 void *p_evas_object )
1197 assert (p_mi != NULL);
1198 #ifdef HAVE_EVAS
1199 var_SetString (p_mi, "vout", "evas");
1200 var_SetString (p_mi, "window", "none");
1201 var_SetAddress (p_mi, "drawable-evasobject", p_evas_object);
1202 return 0;
1203 #else
1204 (void) p_mi; (void) p_evas_object;
1205 return -1;
1206 #endif
1209 void libvlc_audio_set_callbacks( libvlc_media_player_t *mp,
1210 libvlc_audio_play_cb play_cb,
1211 libvlc_audio_pause_cb pause_cb,
1212 libvlc_audio_resume_cb resume_cb,
1213 libvlc_audio_flush_cb flush_cb,
1214 libvlc_audio_drain_cb drain_cb,
1215 void *opaque )
1217 var_SetAddress( mp, "amem-play", play_cb );
1218 var_SetAddress( mp, "amem-pause", pause_cb );
1219 var_SetAddress( mp, "amem-resume", resume_cb );
1220 var_SetAddress( mp, "amem-flush", flush_cb );
1221 var_SetAddress( mp, "amem-drain", drain_cb );
1222 var_SetAddress( mp, "amem-data", opaque );
1223 var_SetString( mp, "aout", "amem,none" );
1225 input_resource_ResetAout(mp->input.p_resource);
1228 void libvlc_audio_set_volume_callback( libvlc_media_player_t *mp,
1229 libvlc_audio_set_volume_cb cb )
1231 var_SetAddress( mp, "amem-set-volume", cb );
1233 input_resource_ResetAout(mp->input.p_resource);
1236 void libvlc_audio_set_format_callbacks( libvlc_media_player_t *mp,
1237 libvlc_audio_setup_cb setup,
1238 libvlc_audio_cleanup_cb cleanup )
1240 var_SetAddress( mp, "amem-setup", setup );
1241 var_SetAddress( mp, "amem-cleanup", cleanup );
1243 input_resource_ResetAout(mp->input.p_resource);
1246 void libvlc_audio_set_format( libvlc_media_player_t *mp, const char *format,
1247 unsigned rate, unsigned channels )
1249 var_SetString( mp, "amem-format", format );
1250 var_SetInteger( mp, "amem-rate", rate );
1251 var_SetInteger( mp, "amem-channels", channels );
1253 input_resource_ResetAout(mp->input.p_resource);
1257 /**************************************************************************
1258 * Getters for stream information
1259 **************************************************************************/
1260 libvlc_time_t libvlc_media_player_get_length(
1261 libvlc_media_player_t *p_mi )
1263 input_thread_t *p_input_thread;
1264 libvlc_time_t i_time;
1266 p_input_thread = libvlc_get_input_thread ( p_mi );
1267 if( !p_input_thread )
1268 return -1;
1270 i_time = from_mtime(var_GetInteger( p_input_thread, "length" ));
1271 vlc_object_release( p_input_thread );
1273 return i_time;
1276 libvlc_time_t libvlc_media_player_get_time( libvlc_media_player_t *p_mi )
1278 input_thread_t *p_input_thread;
1279 libvlc_time_t i_time;
1281 p_input_thread = libvlc_get_input_thread ( p_mi );
1282 if( !p_input_thread )
1283 return -1;
1285 i_time = from_mtime(var_GetInteger( p_input_thread , "time" ));
1286 vlc_object_release( p_input_thread );
1287 return i_time;
1290 void libvlc_media_player_set_time( libvlc_media_player_t *p_mi,
1291 libvlc_time_t i_time )
1293 input_thread_t *p_input_thread;
1295 p_input_thread = libvlc_get_input_thread ( p_mi );
1296 if( !p_input_thread )
1297 return;
1299 var_SetInteger( p_input_thread, "time", to_mtime(i_time) );
1300 vlc_object_release( p_input_thread );
1303 void libvlc_media_player_set_position( libvlc_media_player_t *p_mi,
1304 float position )
1306 input_thread_t *p_input_thread;
1308 p_input_thread = libvlc_get_input_thread ( p_mi );
1309 if( !p_input_thread )
1310 return;
1312 var_SetFloat( p_input_thread, "position", position );
1313 vlc_object_release( p_input_thread );
1316 float libvlc_media_player_get_position( libvlc_media_player_t *p_mi )
1318 input_thread_t *p_input_thread;
1319 float f_position;
1321 p_input_thread = libvlc_get_input_thread ( p_mi );
1322 if( !p_input_thread )
1323 return -1.0;
1325 f_position = var_GetFloat( p_input_thread, "position" );
1326 vlc_object_release( p_input_thread );
1328 return f_position;
1331 void libvlc_media_player_set_chapter( libvlc_media_player_t *p_mi,
1332 int chapter )
1334 input_thread_t *p_input_thread;
1336 p_input_thread = libvlc_get_input_thread ( p_mi );
1337 if( !p_input_thread )
1338 return;
1340 var_SetInteger( p_input_thread, "chapter", chapter );
1341 vlc_object_release( p_input_thread );
1344 int libvlc_media_player_get_chapter( libvlc_media_player_t *p_mi )
1346 input_thread_t *p_input_thread;
1347 int i_chapter;
1349 p_input_thread = libvlc_get_input_thread ( p_mi );
1350 if( !p_input_thread )
1351 return -1;
1353 i_chapter = var_GetInteger( p_input_thread, "chapter" );
1354 vlc_object_release( p_input_thread );
1356 return i_chapter;
1359 int libvlc_media_player_get_chapter_count( libvlc_media_player_t *p_mi )
1361 input_thread_t *p_input_thread;
1362 vlc_value_t val;
1364 p_input_thread = libvlc_get_input_thread ( p_mi );
1365 if( !p_input_thread )
1366 return -1;
1368 int i_ret = var_Change( p_input_thread, "chapter", VLC_VAR_CHOICESCOUNT, &val, NULL );
1369 vlc_object_release( p_input_thread );
1371 return i_ret == VLC_SUCCESS ? val.i_int : -1;
1374 int libvlc_media_player_get_chapter_count_for_title(
1375 libvlc_media_player_t *p_mi,
1376 int i_title )
1378 vlc_value_t val;
1380 input_thread_t *p_input_thread = libvlc_get_input_thread ( p_mi );
1381 if( !p_input_thread )
1382 return -1;
1384 char psz_name[sizeof ("title ") + 3 * sizeof (int)];
1385 sprintf( psz_name, "title %2u", i_title );
1387 int i_ret = var_Change( p_input_thread, psz_name, VLC_VAR_CHOICESCOUNT, &val, NULL );
1388 vlc_object_release( p_input_thread );
1390 return i_ret == VLC_SUCCESS ? val.i_int : -1;
1393 void libvlc_media_player_set_title( libvlc_media_player_t *p_mi,
1394 int i_title )
1396 input_thread_t *p_input_thread;
1398 p_input_thread = libvlc_get_input_thread ( p_mi );
1399 if( !p_input_thread )
1400 return;
1402 var_SetInteger( p_input_thread, "title", i_title );
1403 vlc_object_release( p_input_thread );
1405 //send event
1406 libvlc_event_t event;
1407 event.type = libvlc_MediaPlayerTitleChanged;
1408 event.u.media_player_title_changed.new_title = i_title;
1409 libvlc_event_send( p_mi->p_event_manager, &event );
1412 int libvlc_media_player_get_title( libvlc_media_player_t *p_mi )
1414 input_thread_t *p_input_thread;
1415 int i_title;
1417 p_input_thread = libvlc_get_input_thread ( p_mi );
1418 if( !p_input_thread )
1419 return -1;
1421 i_title = var_GetInteger( p_input_thread, "title" );
1422 vlc_object_release( p_input_thread );
1424 return i_title;
1427 int libvlc_media_player_get_title_count( libvlc_media_player_t *p_mi )
1429 input_thread_t *p_input_thread;
1430 vlc_value_t val;
1432 p_input_thread = libvlc_get_input_thread ( p_mi );
1433 if( !p_input_thread )
1434 return -1;
1436 int i_ret = var_Change( p_input_thread, "title", VLC_VAR_CHOICESCOUNT, &val, NULL );
1437 vlc_object_release( p_input_thread );
1439 return i_ret == VLC_SUCCESS ? val.i_int : -1;
1442 int libvlc_media_player_get_full_title_descriptions( libvlc_media_player_t *p_mi,
1443 libvlc_title_description_t *** pp_titles )
1445 assert( p_mi );
1447 input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
1449 if( !p_input_thread )
1450 return -1;
1452 input_title_t **p_input_title;
1453 int count;
1455 /* fetch data */
1456 int ret = input_Control( p_input_thread, INPUT_GET_FULL_TITLE_INFO,
1457 &p_input_title, &count );
1458 vlc_object_release( p_input_thread );
1459 if( ret != VLC_SUCCESS )
1460 return -1;
1462 libvlc_title_description_t **titles = malloc( count * sizeof (*titles) );
1463 if( count > 0 && unlikely(titles == NULL) )
1464 return -1;
1466 /* fill array */
1467 for( int i = 0; i < count; i++)
1469 libvlc_title_description_t *title = malloc( sizeof (*title) );
1470 if( unlikely(title == NULL) )
1472 libvlc_title_descriptions_release( titles, i );
1473 return -1;
1475 titles[i] = title;
1477 /* we want to return milliseconds to match the rest of the API */
1478 title->i_duration = p_input_title[i]->i_length / 1000;
1479 title->i_flags = p_input_title[i]->i_flags;
1480 if( p_input_title[i]->psz_name )
1481 title->psz_name = strdup( p_input_title[i]->psz_name );
1482 else
1483 title->psz_name = NULL;
1484 vlc_input_title_Delete( p_input_title[i] );
1486 free( p_input_title );
1488 *pp_titles = titles;
1489 return count;
1492 void libvlc_title_descriptions_release( libvlc_title_description_t **p_titles,
1493 unsigned i_count )
1495 for (unsigned i = 0; i < i_count; i++ )
1497 if ( !p_titles[i] )
1498 continue;
1500 free( p_titles[i]->psz_name );
1501 free( p_titles[i] );
1503 free( p_titles );
1506 int libvlc_media_player_get_full_chapter_descriptions( libvlc_media_player_t *p_mi,
1507 int i_chapters_of_title,
1508 libvlc_chapter_description_t *** pp_chapters )
1510 assert( p_mi );
1512 input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
1514 if( !p_input_thread )
1515 return -1;
1517 seekpoint_t **p_seekpoint = NULL;
1519 /* fetch data */
1520 int ret = input_Control(p_input_thread, INPUT_GET_SEEKPOINTS, &p_seekpoint, &i_chapters_of_title);
1521 vlc_object_release( p_input_thread );
1523 if( ret != VLC_SUCCESS)
1525 return -1;
1528 if (i_chapters_of_title == 0 || p_seekpoint == NULL)
1530 return 0;
1533 const int ci_chapter_count = (const int)i_chapters_of_title;
1535 *pp_chapters = calloc( ci_chapter_count, sizeof(**pp_chapters) );
1536 if( !*pp_chapters )
1538 return -1;
1541 /* fill array */
1542 for( int i = 0; i < ci_chapter_count; i++)
1544 libvlc_chapter_description_t *p_chapter = malloc( sizeof(*p_chapter) );
1545 if( unlikely(p_chapter == NULL) )
1547 libvlc_chapter_descriptions_release( *pp_chapters, ci_chapter_count );
1548 return -1;
1550 (*pp_chapters)[i] = p_chapter;
1552 p_chapter->i_time_offset = p_seekpoint[i]->i_time_offset / 1000;
1554 if( i > 0 )
1556 p_chapter->i_duration = p_chapter->i_time_offset - (*pp_chapters)[i-1]->i_time_offset;
1558 else
1560 p_chapter->i_duration = p_chapter->i_time_offset;
1563 if( p_seekpoint[i]->psz_name )
1565 p_chapter->psz_name = strdup( p_seekpoint[i]->psz_name );
1567 else
1569 p_chapter->psz_name = NULL;
1571 vlc_seekpoint_Delete( p_seekpoint[i] );
1574 return ci_chapter_count;
1577 void libvlc_chapter_descriptions_release( libvlc_chapter_description_t **p_chapters,
1578 unsigned i_count )
1580 for (unsigned i = 0; i < i_count; i++ )
1582 if ( !p_chapters[i] )
1583 continue;
1585 free( p_chapters[i]->psz_name );
1586 free( p_chapters[i] );
1588 free( p_chapters );
1591 void libvlc_media_player_next_chapter( libvlc_media_player_t *p_mi )
1593 input_thread_t *p_input_thread;
1595 p_input_thread = libvlc_get_input_thread ( p_mi );
1596 if( !p_input_thread )
1597 return;
1599 int i_type = var_Type( p_input_thread, "next-chapter" );
1600 var_TriggerCallback( p_input_thread, (i_type & VLC_VAR_TYPE) != 0 ?
1601 "next-chapter":"next-title" );
1603 vlc_object_release( p_input_thread );
1606 void libvlc_media_player_previous_chapter( libvlc_media_player_t *p_mi )
1608 input_thread_t *p_input_thread;
1610 p_input_thread = libvlc_get_input_thread ( p_mi );
1611 if( !p_input_thread )
1612 return;
1614 int i_type = var_Type( p_input_thread, "next-chapter" );
1615 var_TriggerCallback( p_input_thread, (i_type & VLC_VAR_TYPE) != 0 ?
1616 "prev-chapter":"prev-title" );
1618 vlc_object_release( p_input_thread );
1621 float libvlc_media_player_get_fps( libvlc_media_player_t *p_mi )
1623 libvlc_media_t *media = libvlc_media_player_get_media( p_mi );
1624 if( media == NULL )
1625 return 0.f;
1627 input_item_t *item = p_mi->p_md->p_input_item;
1628 float fps = 0.f;
1630 vlc_mutex_lock( &item->lock );
1631 for( int i = 0; i < item->i_es; i++ )
1633 const es_format_t *fmt = item->es[i];
1635 if( fmt->i_cat == VIDEO_ES && fmt->video.i_frame_rate_base > 0 )
1636 fps = (float)fmt->video.i_frame_rate
1637 / (float)fmt->video.i_frame_rate_base;
1639 vlc_mutex_unlock( &item->lock );
1641 return fps;
1644 int libvlc_media_player_will_play( libvlc_media_player_t *p_mi )
1646 input_thread_t *p_input_thread =
1647 libvlc_get_input_thread ( p_mi );
1648 if ( !p_input_thread )
1649 return false;
1651 int state = var_GetInteger( p_input_thread, "state" );
1652 vlc_object_release( p_input_thread );
1654 return state != END_S && state != ERROR_S;
1657 int libvlc_media_player_set_rate( libvlc_media_player_t *p_mi, float rate )
1659 var_SetFloat (p_mi, "rate", rate);
1661 input_thread_t *p_input_thread = libvlc_get_input_thread ( p_mi );
1662 if( !p_input_thread )
1663 return 0;
1664 var_SetFloat( p_input_thread, "rate", rate );
1665 vlc_object_release( p_input_thread );
1666 return 0;
1669 float libvlc_media_player_get_rate( libvlc_media_player_t *p_mi )
1671 return var_GetFloat (p_mi, "rate");
1674 libvlc_state_t libvlc_media_player_get_state( libvlc_media_player_t *p_mi )
1676 lock(p_mi);
1677 libvlc_state_t state = p_mi->state;
1678 unlock(p_mi);
1679 return state;
1682 int libvlc_media_player_is_seekable( libvlc_media_player_t *p_mi )
1684 input_thread_t *p_input_thread;
1685 bool b_seekable;
1687 p_input_thread = libvlc_get_input_thread ( p_mi );
1688 if ( !p_input_thread )
1689 return false;
1690 b_seekable = var_GetBool( p_input_thread, "can-seek" );
1691 vlc_object_release( p_input_thread );
1693 return b_seekable;
1696 void libvlc_media_player_navigate( libvlc_media_player_t* p_mi,
1697 unsigned navigate )
1699 static const vlc_action_t map[] =
1701 INPUT_NAV_ACTIVATE, INPUT_NAV_UP, INPUT_NAV_DOWN,
1702 INPUT_NAV_LEFT, INPUT_NAV_RIGHT,
1705 if( navigate >= sizeof(map) / sizeof(map[0]) )
1706 return;
1708 input_thread_t *p_input = libvlc_get_input_thread ( p_mi );
1709 if ( p_input == NULL )
1710 return;
1712 input_Control( p_input, map[navigate], NULL );
1713 vlc_object_release( p_input );
1716 /* internal function, used by audio, video */
1717 libvlc_track_description_t *
1718 libvlc_get_track_description( libvlc_media_player_t *p_mi,
1719 const char *psz_variable )
1721 input_thread_t *p_input = libvlc_get_input_thread( p_mi );
1722 libvlc_track_description_t *p_track_description = NULL,
1723 *p_actual, *p_previous;
1725 if( !p_input )
1726 return NULL;
1728 vlc_value_t val_list, text_list;
1729 int i_ret = var_Change( p_input, psz_variable, VLC_VAR_GETCHOICES, &val_list, &text_list );
1730 if( i_ret != VLC_SUCCESS )
1731 return NULL;
1733 /* no tracks */
1734 if( val_list.p_list->i_count <= 0 )
1735 goto end;
1737 p_track_description = ( libvlc_track_description_t * )
1738 malloc( sizeof( libvlc_track_description_t ) );
1739 if ( !p_track_description )
1741 libvlc_printerr( "Not enough memory" );
1742 goto end;
1744 p_actual = p_track_description;
1745 p_previous = NULL;
1746 for( int i = 0; i < val_list.p_list->i_count; i++ )
1748 if( !p_actual )
1750 p_actual = ( libvlc_track_description_t * )
1751 malloc( sizeof( libvlc_track_description_t ) );
1752 if ( !p_actual )
1754 libvlc_track_description_list_release( p_track_description );
1755 libvlc_printerr( "Not enough memory" );
1756 goto end;
1759 p_actual->i_id = val_list.p_list->p_values[i].i_int;
1760 p_actual->psz_name = strdup( text_list.p_list->p_values[i].psz_string );
1761 p_actual->p_next = NULL;
1762 if( p_previous )
1763 p_previous->p_next = p_actual;
1764 p_previous = p_actual;
1765 p_actual = NULL;
1768 end:
1769 var_FreeList( &val_list, &text_list );
1770 vlc_object_release( p_input );
1772 return p_track_description;
1775 // Deprecated alias for libvlc_track_description_list_release
1776 void libvlc_track_description_release( libvlc_track_description_t *p_td )
1778 libvlc_track_description_list_release( p_td );
1781 void libvlc_track_description_list_release( libvlc_track_description_t *p_td )
1783 libvlc_track_description_t *p_actual, *p_before;
1784 p_actual = p_td;
1786 while ( p_actual )
1788 free( p_actual->psz_name );
1789 p_before = p_actual;
1790 p_actual = p_before->p_next;
1791 free( p_before );
1795 int libvlc_media_player_can_pause( libvlc_media_player_t *p_mi )
1797 input_thread_t *p_input_thread;
1798 bool b_can_pause;
1800 p_input_thread = libvlc_get_input_thread ( p_mi );
1801 if ( !p_input_thread )
1802 return false;
1803 b_can_pause = var_GetBool( p_input_thread, "can-pause" );
1804 vlc_object_release( p_input_thread );
1806 return b_can_pause;
1809 int libvlc_media_player_program_scrambled( libvlc_media_player_t *p_mi )
1811 input_thread_t *p_input_thread;
1812 bool b_program_scrambled;
1814 p_input_thread = libvlc_get_input_thread ( p_mi );
1815 if ( !p_input_thread )
1816 return false;
1817 b_program_scrambled = var_GetBool( p_input_thread, "program-scrambled" );
1818 vlc_object_release( p_input_thread );
1820 return b_program_scrambled;
1823 void libvlc_media_player_next_frame( libvlc_media_player_t *p_mi )
1825 input_thread_t *p_input_thread = libvlc_get_input_thread ( p_mi );
1826 if( p_input_thread != NULL )
1828 var_TriggerCallback( p_input_thread, "frame-next" );
1829 vlc_object_release( p_input_thread );
1834 * Private lookup table to get subpicture alignment flag values corresponding
1835 * to a libvlc_position_t enumerated value.
1837 static const unsigned char position_subpicture_alignment[] = {
1838 [libvlc_position_center] = 0,
1839 [libvlc_position_left] = SUBPICTURE_ALIGN_LEFT,
1840 [libvlc_position_right] = SUBPICTURE_ALIGN_RIGHT,
1841 [libvlc_position_top] = SUBPICTURE_ALIGN_TOP,
1842 [libvlc_position_top_left] = SUBPICTURE_ALIGN_TOP | SUBPICTURE_ALIGN_LEFT,
1843 [libvlc_position_top_right] = SUBPICTURE_ALIGN_TOP | SUBPICTURE_ALIGN_RIGHT,
1844 [libvlc_position_bottom] = SUBPICTURE_ALIGN_BOTTOM,
1845 [libvlc_position_bottom_left] = SUBPICTURE_ALIGN_BOTTOM | SUBPICTURE_ALIGN_LEFT,
1846 [libvlc_position_bottom_right] = SUBPICTURE_ALIGN_BOTTOM | SUBPICTURE_ALIGN_RIGHT
1849 void libvlc_media_player_set_video_title_display( libvlc_media_player_t *p_mi, libvlc_position_t position, unsigned timeout )
1851 assert( position >= libvlc_position_disable && position <= libvlc_position_bottom_right );
1853 if ( position != libvlc_position_disable )
1855 var_SetBool( p_mi, "video-title-show", true );
1856 var_SetInteger( p_mi, "video-title-position", position_subpicture_alignment[position] );
1857 var_SetInteger( p_mi, "video-title-timeout", timeout );
1859 else
1861 var_SetBool( p_mi, "video-title-show", false );
1866 * Maximum size of a formatted equalizer amplification band frequency value.
1868 * The allowed value range is supposed to be constrained from -20.0 to 20.0.
1870 * The format string " %.07f" with a minimum value of "-20" gives a maximum
1871 * string length of e.g. " -19.1234567", i.e. 12 bytes (not including the null
1872 * terminator).
1874 #define EQZ_BAND_VALUE_SIZE 12
1876 int libvlc_media_player_set_equalizer( libvlc_media_player_t *p_mi, libvlc_equalizer_t *p_equalizer )
1878 char bands[EQZ_BANDS_MAX * EQZ_BAND_VALUE_SIZE + 1];
1880 if( p_equalizer != NULL )
1882 for( unsigned i = 0, c = 0; i < EQZ_BANDS_MAX; i++ )
1884 c += snprintf( bands + c, sizeof(bands) - c, " %.07f",
1885 p_equalizer->f_amp[i] );
1886 if( unlikely(c >= sizeof(bands)) )
1887 return -1;
1890 var_SetFloat( p_mi, "equalizer-preamp", p_equalizer->f_preamp );
1891 var_SetString( p_mi, "equalizer-bands", bands );
1893 var_SetString( p_mi, "audio-filter", p_equalizer ? "equalizer" : "" );
1895 audio_output_t *p_aout = input_resource_HoldAout( p_mi->input.p_resource );
1896 if( p_aout != NULL )
1898 if( p_equalizer != NULL )
1900 var_SetFloat( p_aout, "equalizer-preamp", p_equalizer->f_preamp );
1901 var_SetString( p_aout, "equalizer-bands", bands );
1904 var_SetString( p_aout, "audio-filter", p_equalizer ? "equalizer" : "" );
1905 vlc_object_release( p_aout );
1908 return 0;