player: add a metadata listener API
[vlc.git] / lib / media_player.c
blob6ec6025022b3dc1587b7ca8e1c84da62f84b6b06
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_renderer_discoverer.h>
31 #include <vlc/libvlc_picture.h>
32 #include <vlc/libvlc_media.h>
33 #include <vlc/libvlc_events.h>
35 #include <vlc_demux.h>
36 #include <vlc_vout.h>
37 #include <vlc_aout.h>
38 #include <vlc_actions.h>
39 #include <vlc_http.h>
41 #include "libvlc_internal.h"
42 #include "media_internal.h" // libvlc_media_set_state()
43 #include "media_player_internal.h"
44 #include "renderer_discoverer_internal.h"
46 #define ES_INIT (-2) /* -1 is reserved for ES deselect */
48 static int
49 snapshot_was_taken( vlc_object_t *p_this, char const *psz_cmd,
50 vlc_value_t oldval, vlc_value_t newval, void *p_data );
52 static void media_attach_preparsed_event(libvlc_media_t *);
53 static void media_detach_preparsed_event(libvlc_media_t *);
55 static void libvlc_media_player_destroy( libvlc_media_player_t *p_mi );
57 // player callbacks
59 static void
60 on_current_media_changed(vlc_player_t *player, input_item_t *new_media,
61 void *data)
63 (void) player;
65 libvlc_media_player_t *mp = data;
67 libvlc_media_t *md = mp->p_md;
69 input_item_t *media = md ? md->p_input_item : NULL;
70 if (new_media == media)
71 /* no changes */
72 return;
74 if (md)
75 media_detach_preparsed_event(md);
77 if (new_media)
79 mp->p_md = libvlc_media_new_from_input_item(mp->p_libvlc_instance,
80 new_media);
81 if (!mp->p_md)
82 /* error already printed by the function call */
83 return;
85 media_attach_preparsed_event(mp->p_md);
87 else
88 mp->p_md = NULL;
90 libvlc_media_release(md);
92 libvlc_event_t event;
93 event.type = libvlc_MediaPlayerMediaChanged;
94 event.u.media_player_media_changed.new_media = mp->p_md;
95 libvlc_event_send(&mp->event_manager, &event);
98 static void
99 on_state_changed(vlc_player_t *player, enum vlc_player_state new_state,
100 void *data)
102 (void) player;
104 libvlc_media_player_t *mp = data;
106 libvlc_event_t event;
107 switch (new_state) {
108 case VLC_PLAYER_STATE_STOPPED:
109 event.type = libvlc_MediaPlayerStopped;
110 break;
111 case VLC_PLAYER_STATE_STOPPING:
112 event.type = libvlc_MediaPlayerEndReached;
113 break;
114 case VLC_PLAYER_STATE_STARTED:
115 event.type = libvlc_MediaPlayerOpening;
116 break;
117 case VLC_PLAYER_STATE_PLAYING:
118 event.type = libvlc_MediaPlayerPlaying;
119 break;
120 case VLC_PLAYER_STATE_PAUSED:
121 event.type = libvlc_MediaPlayerPaused;
122 break;
123 default:
124 vlc_assert_unreachable();
127 libvlc_event_send(&mp->event_manager, &event);
130 static void
131 on_error_changed(vlc_player_t *player, enum vlc_player_error error, void *data)
133 (void) player;
135 libvlc_media_player_t *mp = data;
137 libvlc_event_t event;
138 switch (error) {
139 case VLC_PLAYER_ERROR_NONE:
140 event.type = libvlc_MediaPlayerNothingSpecial;
141 break;
142 case VLC_PLAYER_ERROR_GENERIC:
143 event.type = libvlc_MediaPlayerEncounteredError;
144 break;
145 default:
146 vlc_assert_unreachable();
149 libvlc_event_send(&mp->event_manager, &event);
152 static void
153 on_buffering_changed(vlc_player_t *player, float new_buffering, void *data)
155 (void) player;
157 libvlc_media_player_t *mp = data;
159 libvlc_event_t event;
160 event.type = libvlc_MediaPlayerBuffering;
161 event.u.media_player_buffering.new_cache = 100 * new_buffering;
163 libvlc_event_send(&mp->event_manager, &event);
166 static void
167 on_capabilities_changed(vlc_player_t *player, int old_caps, int new_caps, void *data)
169 (void) player;
171 libvlc_media_player_t *mp = data;
173 libvlc_event_t event;
175 bool old_seekable = old_caps & VLC_PLAYER_CAP_SEEK;
176 bool new_seekable = new_caps & VLC_PLAYER_CAP_SEEK;
177 if (new_seekable != old_seekable)
179 event.type = libvlc_MediaPlayerSeekableChanged;
180 event.u.media_player_seekable_changed.new_seekable = new_seekable;
181 libvlc_event_send(&mp->event_manager, &event);
184 bool old_pauseable = old_caps & VLC_PLAYER_CAP_PAUSE;
185 bool new_pauseable = new_caps & VLC_PLAYER_CAP_PAUSE;
186 if (new_pauseable != old_pauseable)
188 event.type = libvlc_MediaPlayerPausableChanged;
189 event.u.media_player_pausable_changed.new_pausable = new_pauseable;
190 libvlc_event_send(&mp->event_manager, &event);
194 static void
195 on_position_changed(vlc_player_t *player, vlc_tick_t new_time, float new_pos,
196 void *data)
198 (void) player;
200 libvlc_media_player_t *mp = data;
202 libvlc_event_t event;
204 event.type = libvlc_MediaPlayerPositionChanged;
205 event.u.media_player_position_changed.new_position = new_pos;
206 libvlc_event_send(&mp->event_manager, &event);
208 event.type = libvlc_MediaPlayerTimeChanged;
209 event.u.media_player_time_changed.new_time = MS_FROM_VLC_TICK(new_time);
210 libvlc_event_send(&mp->event_manager, &event);
213 static void
214 on_length_changed(vlc_player_t *player, vlc_tick_t new_length, void *data)
216 (void) player;
218 libvlc_media_player_t *mp = data;
220 libvlc_event_t event;
222 event.type = libvlc_MediaPlayerLengthChanged;
223 event.u.media_player_length_changed.new_length =
224 MS_FROM_VLC_TICK(new_length);
226 libvlc_event_send(&mp->event_manager, &event);
229 static int
230 track_type_from_cat(enum es_format_category_e cat)
232 switch (cat)
234 case VIDEO_ES:
235 return libvlc_track_video;
236 case AUDIO_ES:
237 return libvlc_track_audio;
238 case SPU_ES:
239 return libvlc_track_text;
240 default:
241 return libvlc_track_unknown;
245 static void
246 on_track_list_changed(vlc_player_t *player, enum vlc_player_list_action action,
247 const struct vlc_player_track *track, void *data)
249 (void) player;
251 libvlc_media_player_t *mp = data;
253 libvlc_event_t event;
254 switch (action)
256 case VLC_PLAYER_LIST_ADDED:
257 event.type = libvlc_MediaPlayerESAdded; break;
258 case VLC_PLAYER_LIST_REMOVED:
259 event.type = libvlc_MediaPlayerESDeleted; break;
260 case VLC_PLAYER_LIST_UPDATED:
261 event.type = libvlc_MediaPlayerESUpdated; break;
264 event.u.media_player_es_changed.i_type =
265 track_type_from_cat(track->fmt.i_cat);
266 event.u.media_player_es_changed.i_id = vlc_es_id_GetInputId(track->es_id);
267 event.u.media_player_es_changed.psz_id = vlc_es_id_GetStrId(track->es_id);
269 libvlc_event_send(&mp->event_manager, &event);
272 static void
273 on_track_selection_changed(vlc_player_t *player, vlc_es_id_t *unselected_id,
274 vlc_es_id_t *selected_id, void *data)
276 (void) player;
277 (void) unselected_id;
279 libvlc_media_player_t *mp = data;
281 libvlc_event_t event;
282 event.type = libvlc_MediaPlayerESSelected;
284 if (unselected_id)
286 enum es_format_category_e cat = vlc_es_id_GetCat(unselected_id);
287 event.u.media_player_es_selection_changed.i_type = track_type_from_cat(cat);
289 if (selected_id)
291 enum es_format_category_e cat = vlc_es_id_GetCat(selected_id);
292 event.u.media_player_es_selection_changed.i_type = track_type_from_cat(cat);
295 event.u.media_player_es_selection_changed.psz_unselected_id =
296 unselected_id ? vlc_es_id_GetStrId(unselected_id) : NULL;
298 event.u.media_player_es_selection_changed.psz_selected_id =
299 selected_id ? vlc_es_id_GetStrId(selected_id) : NULL;
301 libvlc_event_send(&mp->event_manager, &event);
304 static void
305 on_program_list_changed(vlc_player_t *player,
306 enum vlc_player_list_action action,
307 const struct vlc_player_program *prgm, void* data)
309 (void) action;
310 (void) prgm;
312 libvlc_media_player_t *mp = data;
314 const struct vlc_player_program *selected =
315 vlc_player_GetSelectedProgram(player);
316 if (!selected)
317 return;
319 libvlc_event_t event;
320 event.type = libvlc_MediaPlayerScrambledChanged;
321 event.u.media_player_scrambled_changed.new_scrambled = selected->scrambled;
323 libvlc_event_send(&mp->event_manager, &event);
326 static void
327 on_program_selection_changed(vlc_player_t *player, int unselected_id,
328 int selected_id, void *data)
330 (void) unselected_id;
332 libvlc_media_player_t *mp = data;
334 if (selected_id == -1)
335 return;
337 const struct vlc_player_program *program =
338 vlc_player_GetSelectedProgram(player);
340 if (unlikely(program == NULL)) /* can happen when the player is stopping */
341 return;
343 libvlc_event_t event;
344 event.type = libvlc_MediaPlayerScrambledChanged;
345 event.u.media_player_scrambled_changed.new_scrambled = program->scrambled;
347 libvlc_event_send(&mp->event_manager, &event);
350 static void
351 on_titles_changed(vlc_player_t *player,
352 vlc_player_title_list *titles, void *data)
354 (void) player;
355 (void) titles;
357 libvlc_media_player_t *mp = data;
359 libvlc_event_t event;
360 event.type = libvlc_MediaPlayerTitleListChanged;
362 libvlc_event_send(&mp->event_manager, &event);
365 static void
366 on_title_selection_changed(vlc_player_t *player,
367 const struct vlc_player_title *new_title,
368 size_t new_idx, void *data)
370 (void) player;
371 (void) new_title;
373 libvlc_media_player_t *mp = data;
375 const libvlc_title_description_t libtitle = {
376 .i_duration = MS_FROM_VLC_TICK(new_title->length),
377 .psz_name = (char *) new_title->name,
378 .i_flags = new_title->flags,
381 libvlc_event_t event;
382 event.type = libvlc_MediaPlayerTitleSelectionChanged;
383 event.u.media_player_title_selection_changed.title = &libtitle;
384 event.u.media_player_title_selection_changed.index = new_idx;
386 libvlc_event_send(&mp->event_manager, &event);
389 static void
390 on_chapter_selection_changed(vlc_player_t *player,
391 const struct vlc_player_title *title,
392 size_t title_idx,
393 const struct vlc_player_chapter *new_chapter,
394 size_t new_chapter_idx,
395 void *data)
397 (void) player;
398 (void) title;
399 (void) title_idx;
400 (void) new_chapter;
402 libvlc_media_player_t *mp = data;
404 libvlc_event_t event;
405 event.type = libvlc_MediaPlayerChapterChanged;
406 event.u.media_player_chapter_changed.new_chapter = new_chapter_idx;
408 libvlc_event_send(&mp->event_manager, &event);
411 static void
412 on_media_subitems_changed(vlc_player_t *player, input_item_t *media,
413 input_item_node_t *new_subitems, void *data)
415 (void) player;
417 libvlc_media_player_t *mp = data;
419 input_item_t *current = mp->p_md ? mp->p_md->p_input_item : NULL;
420 if (media == current)
421 libvlc_media_add_subtree(mp->p_md, new_subitems);
424 static void
425 on_cork_changed(vlc_player_t *player, unsigned cork_count, void *data)
427 (void) player;
429 libvlc_media_player_t *mp = data;
431 libvlc_event_t event;
432 event.type = cork_count ? libvlc_MediaPlayerCorked
433 : libvlc_MediaPlayerUncorked;
435 libvlc_event_send(&mp->event_manager, &event);
438 static void
439 on_vout_changed(vlc_player_t *player, enum vlc_player_vout_action action,
440 vout_thread_t *vout, enum vlc_vout_order order,
441 vlc_es_id_t *es_id, void *data)
443 (void) action;
444 (void) vout;
445 (void) order;
447 if (vlc_es_id_GetCat(es_id) != VIDEO_ES)
448 return;
450 libvlc_media_player_t *mp = data;
452 size_t count;
453 vout_thread_t **vouts = vlc_player_vout_HoldAll(player, &count);
454 if (!vouts)
455 return;
456 for (size_t i = 0; i < count; ++i)
457 vout_Release(vouts[i]);
458 free(vouts);
460 libvlc_event_t event;
461 event.type = libvlc_MediaPlayerVout;
462 event.u.media_player_vout.new_count = count;
464 libvlc_event_send(&mp->event_manager, &event);
467 // player aout callbacks
469 static void
470 on_volume_changed(audio_output_t *aout, float new_volume, void *data)
472 (void) aout;
474 libvlc_media_player_t *mp = data;
476 libvlc_event_t event;
477 event.type = libvlc_MediaPlayerAudioVolume;
478 event.u.media_player_audio_volume.volume = new_volume;
480 libvlc_event_send(&mp->event_manager, &event);
483 static void
484 on_mute_changed(audio_output_t *aout, bool new_muted, void *data)
486 (void) aout;
488 libvlc_media_player_t *mp = data;
490 libvlc_event_t event;
491 event.type = new_muted ? libvlc_MediaPlayerMuted
492 : libvlc_MediaPlayerUnmuted;
494 libvlc_event_send(&mp->event_manager, &event);
497 static void
498 on_audio_device_changed(audio_output_t *aout, const char *device, void *data)
500 (void) aout;
502 libvlc_media_player_t *mp = data;
504 libvlc_event_t event;
505 event.type = libvlc_MediaPlayerAudioDevice;
506 event.u.media_player_audio_device.device = device;
508 libvlc_event_send(&mp->event_manager, &event);
511 static const struct vlc_player_cbs vlc_player_cbs = {
512 .on_current_media_changed = on_current_media_changed,
513 .on_state_changed = on_state_changed,
514 .on_error_changed = on_error_changed,
515 .on_buffering_changed = on_buffering_changed,
516 .on_capabilities_changed = on_capabilities_changed,
517 .on_position_changed = on_position_changed,
518 .on_length_changed = on_length_changed,
519 .on_track_list_changed = on_track_list_changed,
520 .on_track_selection_changed = on_track_selection_changed,
521 .on_program_list_changed = on_program_list_changed,
522 .on_program_selection_changed = on_program_selection_changed,
523 .on_titles_changed = on_titles_changed,
524 .on_title_selection_changed = on_title_selection_changed,
525 .on_chapter_selection_changed = on_chapter_selection_changed,
526 .on_media_subitems_changed = on_media_subitems_changed,
527 .on_cork_changed = on_cork_changed,
528 .on_vout_changed = on_vout_changed,
531 static const struct vlc_player_aout_cbs vlc_player_aout_cbs = {
532 .on_volume_changed = on_volume_changed,
533 .on_mute_changed = on_mute_changed,
534 .on_device_changed = on_audio_device_changed,
537 /**************************************************************************
538 * Snapshot Taken Event.
540 * FIXME: This snapshot API interface makes no sense in media_player.
541 *************************************************************************/
542 static int snapshot_was_taken(vlc_object_t *p_this, char const *psz_cmd,
543 vlc_value_t oldval, vlc_value_t newval, void *p_data )
545 VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval); VLC_UNUSED(p_this);
547 libvlc_media_player_t *mp = p_data;
548 libvlc_event_t event;
549 event.type = libvlc_MediaPlayerSnapshotTaken;
550 event.u.media_player_snapshot_taken.psz_filename = newval.psz_string;
551 libvlc_event_send(&mp->event_manager, &event);
553 return VLC_SUCCESS;
556 static void input_item_preparsed_changed( const vlc_event_t *p_event,
557 void * user_data )
559 libvlc_media_t *p_md = user_data;
560 if( p_event->u.input_item_preparsed_changed.new_status & ITEM_PREPARSED )
562 /* Send the event */
563 libvlc_event_t event;
564 event.type = libvlc_MediaParsedChanged;
565 event.u.media_parsed_changed.new_status = libvlc_media_parsed_status_done;
566 libvlc_event_send( &p_md->event_manager, &event );
570 static void media_attach_preparsed_event( libvlc_media_t *p_md )
572 vlc_event_attach( &p_md->p_input_item->event_manager,
573 vlc_InputItemPreparsedChanged,
574 input_item_preparsed_changed, p_md );
577 static void media_detach_preparsed_event( libvlc_media_t *p_md )
579 vlc_event_detach( &p_md->p_input_item->event_manager,
580 vlc_InputItemPreparsedChanged,
581 input_item_preparsed_changed,
582 p_md );
585 /**************************************************************************
586 * Create a Media Instance object.
588 * Refcount strategy:
589 * - All items created by _new start with a refcount set to 1.
590 * - Accessor _release decrease the refcount by 1, if after that
591 * operation the refcount is 0, the object is destroyed.
592 * - Accessor _retain increase the refcount by 1 (XXX: to implement)
594 * Object locking strategy:
595 * - No lock held while in constructor.
596 * - When accessing any member variable this lock is held. (XXX who locks?)
597 * - When attempting to destroy the object the lock is also held.
598 **************************************************************************/
599 libvlc_media_player_t *
600 libvlc_media_player_new( libvlc_instance_t *instance )
602 libvlc_media_player_t * mp;
604 assert(instance);
606 mp = vlc_object_create (instance->p_libvlc_int, sizeof(*mp));
607 if (unlikely(mp == NULL))
609 libvlc_printerr("Not enough memory");
610 return NULL;
613 /* Input */
614 var_Create (mp, "rate", VLC_VAR_FLOAT|VLC_VAR_DOINHERIT);
615 var_Create (mp, "sout", VLC_VAR_STRING);
616 var_Create (mp, "demux-filter", VLC_VAR_STRING);
618 /* Video */
619 var_Create (mp, "vout", VLC_VAR_STRING|VLC_VAR_DOINHERIT);
620 var_Create (mp, "window", VLC_VAR_STRING);
621 var_Create (mp, "gl", VLC_VAR_STRING);
622 var_Create (mp, "gles2", VLC_VAR_STRING);
623 var_Create (mp, "vmem-lock", VLC_VAR_ADDRESS);
624 var_Create (mp, "vmem-unlock", VLC_VAR_ADDRESS);
625 var_Create (mp, "vmem-display", VLC_VAR_ADDRESS);
626 var_Create (mp, "vmem-data", VLC_VAR_ADDRESS);
627 var_Create (mp, "vmem-setup", VLC_VAR_ADDRESS);
628 var_Create (mp, "vmem-cleanup", VLC_VAR_ADDRESS);
629 var_Create (mp, "vmem-chroma", VLC_VAR_STRING | VLC_VAR_DOINHERIT);
630 var_Create (mp, "vmem-width", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
631 var_Create (mp, "vmem-height", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
632 var_Create (mp, "vmem-pitch", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
634 var_Create (mp, "vout-cb-type", VLC_VAR_INTEGER );
635 var_Create( mp, "vout-cb-opaque", VLC_VAR_ADDRESS );
636 var_Create( mp, "vout-cb-setup", VLC_VAR_ADDRESS );
637 var_Create( mp, "vout-cb-cleanup", VLC_VAR_ADDRESS );
638 var_Create( mp, "vout-cb-resize-cb", VLC_VAR_ADDRESS );
639 var_Create( mp, "vout-cb-update-output", VLC_VAR_ADDRESS );
640 var_Create( mp, "vout-cb-swap", VLC_VAR_ADDRESS );
641 var_Create( mp, "vout-cb-get-proc-address", VLC_VAR_ADDRESS );
642 var_Create( mp, "vout-cb-make-current", VLC_VAR_ADDRESS );
643 var_Create( mp, "vout-cb-metadata", VLC_VAR_ADDRESS );
644 var_Create( mp, "vout-cb-select-plane", VLC_VAR_ADDRESS );
646 var_Create (mp, "dec-dev", VLC_VAR_STRING);
647 var_Create (mp, "drawable-xid", VLC_VAR_INTEGER);
648 #if defined (_WIN32) || defined (__OS2__)
649 var_Create (mp, "drawable-hwnd", VLC_VAR_INTEGER);
650 #endif
651 #ifdef __APPLE__
652 var_Create (mp, "drawable-nsobject", VLC_VAR_ADDRESS);
653 #endif
654 #ifdef __ANDROID__
655 var_Create (mp, "drawable-androidwindow", VLC_VAR_ADDRESS);
656 #endif
658 var_Create (mp, "keyboard-events", VLC_VAR_BOOL);
659 var_SetBool (mp, "keyboard-events", true);
660 var_Create (mp, "mouse-events", VLC_VAR_BOOL);
661 var_SetBool (mp, "mouse-events", true);
663 var_Create (mp, "fullscreen", VLC_VAR_BOOL);
664 var_Create (mp, "autoscale", VLC_VAR_BOOL | VLC_VAR_DOINHERIT);
665 var_Create (mp, "zoom", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT);
666 var_Create (mp, "aspect-ratio", VLC_VAR_STRING);
667 var_Create (mp, "crop", VLC_VAR_STRING);
668 var_Create (mp, "deinterlace", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
669 var_Create (mp, "deinterlace-mode", VLC_VAR_STRING | VLC_VAR_DOINHERIT);
671 var_Create (mp, "vbi-page", VLC_VAR_INTEGER);
672 var_SetInteger (mp, "vbi-page", 100);
674 var_Create (mp, "video-filter", VLC_VAR_STRING | VLC_VAR_DOINHERIT);
675 var_Create (mp, "sub-source", VLC_VAR_STRING | VLC_VAR_DOINHERIT);
676 var_Create (mp, "sub-filter", VLC_VAR_STRING | VLC_VAR_DOINHERIT);
678 var_Create (mp, "marq-marquee", VLC_VAR_STRING);
679 var_Create (mp, "marq-color", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
680 var_Create (mp, "marq-opacity", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
681 var_Create (mp, "marq-position", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
682 var_Create (mp, "marq-refresh", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
683 var_Create (mp, "marq-size", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
684 var_Create (mp, "marq-timeout", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
685 var_Create (mp, "marq-x", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
686 var_Create (mp, "marq-y", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
688 var_Create (mp, "logo-file", VLC_VAR_STRING);
689 var_Create (mp, "logo-x", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
690 var_Create (mp, "logo-y", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
691 var_Create (mp, "logo-delay", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
692 var_Create (mp, "logo-repeat", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
693 var_Create (mp, "logo-opacity", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
694 var_Create (mp, "logo-position", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
696 var_Create (mp, "contrast", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT);
697 var_Create (mp, "brightness", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT);
698 var_Create (mp, "hue", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT);
699 var_Create (mp, "saturation", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT);
700 var_Create (mp, "gamma", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT);
702 /* Audio */
703 var_Create (mp, "aout", VLC_VAR_STRING | VLC_VAR_DOINHERIT);
704 var_Create (mp, "audio-device", VLC_VAR_STRING);
705 var_Create (mp, "mute", VLC_VAR_BOOL);
706 var_Create (mp, "volume", VLC_VAR_FLOAT);
707 var_Create (mp, "corks", VLC_VAR_INTEGER);
708 var_Create (mp, "audio-filter", VLC_VAR_STRING);
709 var_Create (mp, "role", VLC_VAR_STRING | VLC_VAR_DOINHERIT);
710 var_Create (mp, "amem-data", VLC_VAR_ADDRESS);
711 var_Create (mp, "amem-setup", VLC_VAR_ADDRESS);
712 var_Create (mp, "amem-cleanup", VLC_VAR_ADDRESS);
713 var_Create (mp, "amem-play", VLC_VAR_ADDRESS);
714 var_Create (mp, "amem-pause", VLC_VAR_ADDRESS);
715 var_Create (mp, "amem-resume", VLC_VAR_ADDRESS);
716 var_Create (mp, "amem-flush", VLC_VAR_ADDRESS);
717 var_Create (mp, "amem-drain", VLC_VAR_ADDRESS);
718 var_Create (mp, "amem-set-volume", VLC_VAR_ADDRESS);
719 var_Create (mp, "amem-format", VLC_VAR_STRING | VLC_VAR_DOINHERIT);
720 var_Create (mp, "amem-rate", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
721 var_Create (mp, "amem-channels", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
723 /* Video Title */
724 var_Create (mp, "video-title-show", VLC_VAR_BOOL);
725 var_Create (mp, "video-title-position", VLC_VAR_INTEGER);
726 var_Create (mp, "video-title-timeout", VLC_VAR_INTEGER);
728 /* Equalizer */
729 var_Create (mp, "equalizer-preamp", VLC_VAR_FLOAT);
730 var_Create (mp, "equalizer-vlcfreqs", VLC_VAR_BOOL);
731 var_Create (mp, "equalizer-bands", VLC_VAR_STRING);
733 /* Initialize the shared HTTP cookie jar */
734 vlc_value_t cookies;
735 cookies.p_address = vlc_http_cookies_new();
736 if ( likely(cookies.p_address) )
738 var_Create(mp, "http-cookies", VLC_VAR_ADDRESS);
739 var_SetChecked(mp, "http-cookies", VLC_VAR_ADDRESS, cookies);
742 mp->p_md = NULL;
743 mp->p_libvlc_instance = instance;
744 /* use a reentrant lock to allow calling libvlc functions from callbacks */
745 mp->player = vlc_player_New(VLC_OBJECT(mp), VLC_PLAYER_LOCK_REENTRANT,
746 NULL, NULL);
747 if (unlikely(!mp->player))
748 goto error1;
750 vlc_player_Lock(mp->player);
752 mp->listener = vlc_player_AddListener(mp->player, &vlc_player_cbs, mp);
753 if (unlikely(!mp->listener))
754 goto error2;
756 mp->aout_listener =
757 vlc_player_aout_AddListener(mp->player, &vlc_player_aout_cbs, mp);
758 if (unlikely(!mp->aout_listener))
759 goto error3;
761 vlc_player_Unlock(mp->player);
763 mp->i_refcount = 1;
764 libvlc_event_manager_init(&mp->event_manager, mp);
766 /* Snapshot initialization */
767 /* Attach a var callback to the global object to provide the glue between
768 * vout_thread that generates the event and media_player that re-emits it
769 * with its own event manager
771 * FIXME: It's unclear why we want to put this in public API, and why we
772 * want to expose it in such a limiting and ugly way.
774 var_AddCallback(vlc_object_instance(mp),
775 "snapshot-file", snapshot_was_taken, mp);
777 libvlc_retain(instance);
778 return mp;
780 error3:
781 vlc_player_RemoveListener(mp->player, mp->listener);
782 error2:
783 vlc_player_Unlock(mp->player);
784 vlc_player_Delete(mp->player);
785 error1:
786 vlc_object_delete(mp);
787 return NULL;
790 /**************************************************************************
791 * Create a Media Instance object with a media descriptor.
792 **************************************************************************/
793 libvlc_media_player_t *
794 libvlc_media_player_new_from_media( libvlc_media_t * p_md )
796 libvlc_media_player_t * p_mi;
798 p_mi = libvlc_media_player_new( p_md->p_libvlc_instance );
799 if( !p_mi )
800 return NULL;
802 libvlc_media_retain( p_md );
803 p_mi->p_md = p_md;
804 media_attach_preparsed_event(p_md);
806 vlc_player_Lock(p_mi->player);
807 int ret = vlc_player_SetCurrentMedia(p_mi->player, p_md->p_input_item);
808 vlc_player_Unlock(p_mi->player);
810 if (ret != VLC_SUCCESS)
812 media_detach_preparsed_event(p_md);
813 libvlc_media_release(p_md);
814 p_mi->p_md = NULL;
815 return NULL;
818 return p_mi;
821 /**************************************************************************
822 * Destroy a Media Instance object (libvlc internal)
824 * Warning: No lock held here, but hey, this is internal. Caller must lock.
825 **************************************************************************/
826 static void libvlc_media_player_destroy( libvlc_media_player_t *p_mi )
828 assert( p_mi );
830 /* Detach Callback from the main libvlc object */
831 var_DelCallback( vlc_object_instance(p_mi),
832 "snapshot-file", snapshot_was_taken, p_mi );
834 vlc_player_Lock(p_mi->player);
835 vlc_player_aout_RemoveListener(p_mi->player, p_mi->aout_listener);
836 vlc_player_RemoveListener(p_mi->player, p_mi->listener);
837 vlc_player_Unlock(p_mi->player);
839 vlc_player_Delete(p_mi->player);
841 if (p_mi->p_md)
842 media_detach_preparsed_event(p_mi->p_md);
843 libvlc_event_manager_destroy(&p_mi->event_manager);
844 libvlc_media_release( p_mi->p_md );
846 vlc_http_cookie_jar_t *cookies = var_GetAddress( p_mi, "http-cookies" );
847 if ( cookies )
849 var_Destroy( p_mi, "http-cookies" );
850 vlc_http_cookies_destroy( cookies );
853 libvlc_instance_t *instance = p_mi->p_libvlc_instance;
854 vlc_object_delete(p_mi);
855 libvlc_release(instance);
858 /**************************************************************************
859 * Release a Media Instance object.
861 * Function does the locking.
862 **************************************************************************/
863 void libvlc_media_player_release( libvlc_media_player_t *p_mi )
865 bool destroy;
867 assert( p_mi );
868 vlc_player_Lock(p_mi->player);
869 destroy = !--p_mi->i_refcount;
870 vlc_player_Unlock(p_mi->player);
872 if( destroy )
873 libvlc_media_player_destroy( p_mi );
876 /**************************************************************************
877 * Retain a Media Instance object.
879 * Caller must hold the lock.
880 **************************************************************************/
881 void libvlc_media_player_retain( libvlc_media_player_t *p_mi )
883 assert( p_mi );
885 vlc_player_Lock(p_mi->player);
886 p_mi->i_refcount++;
887 vlc_player_Unlock(p_mi->player);
890 /**************************************************************************
891 * Set the Media descriptor associated with the instance.
893 * Enter without lock -- function will lock the object.
894 **************************************************************************/
895 void libvlc_media_player_set_media(
896 libvlc_media_player_t *p_mi,
897 libvlc_media_t *p_md )
899 vlc_player_Lock(p_mi->player);
901 if (p_mi->p_md)
902 media_detach_preparsed_event(p_mi->p_md);
904 libvlc_media_release( p_mi->p_md );
906 if( p_md )
908 libvlc_media_retain( p_md );
909 media_attach_preparsed_event(p_md);
911 p_mi->p_md = p_md;
913 vlc_player_SetCurrentMedia(p_mi->player, p_md->p_input_item);
915 vlc_player_Unlock(p_mi->player);
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 )
924 libvlc_media_t *p_m;
926 vlc_player_Lock(p_mi->player);
927 p_m = p_mi->p_md;
928 if( p_m )
929 libvlc_media_retain( p_m );
930 vlc_player_Unlock(p_mi->player);
932 return p_m;
935 /**************************************************************************
936 * Get the event Manager.
937 **************************************************************************/
938 libvlc_event_manager_t *
939 libvlc_media_player_event_manager( libvlc_media_player_t *p_mi )
941 return &p_mi->event_manager;
944 /**************************************************************************
945 * Tell media player to start playing.
946 **************************************************************************/
947 int libvlc_media_player_play( libvlc_media_player_t *p_mi )
949 vlc_player_t *player = p_mi->player;
950 vlc_player_Lock(player);
952 int ret = vlc_player_Start(player);
953 if (ret == VLC_SUCCESS)
955 if (vlc_player_IsPaused(player))
956 vlc_player_Resume(player);
959 vlc_player_Unlock(player);
960 return ret;
963 void libvlc_media_player_set_pause( libvlc_media_player_t *p_mi, int paused )
965 vlc_player_t *player = p_mi->player;
966 vlc_player_Lock(player);
968 if (paused)
970 if (vlc_player_CanPause(player))
971 vlc_player_Pause(player);
972 else
973 vlc_player_Stop(player);
975 else
977 vlc_player_Resume(player);
980 vlc_player_Unlock(player);
983 /**************************************************************************
984 * Toggle pause.
985 **************************************************************************/
986 void libvlc_media_player_pause( libvlc_media_player_t *p_mi )
988 vlc_player_t *player = p_mi->player;
989 vlc_player_Lock(player);
991 vlc_player_TogglePause(player);
993 vlc_player_Unlock(player);
996 /**************************************************************************
997 * Tells whether the media player is currently playing.
998 **************************************************************************/
999 bool libvlc_media_player_is_playing(libvlc_media_player_t *p_mi)
1001 vlc_player_t *player = p_mi->player;
1002 vlc_player_Lock(player);
1004 bool ret = vlc_player_IsStarted(player) && !vlc_player_IsPaused(player);
1006 vlc_player_Unlock(player);
1007 return ret;
1010 /**************************************************************************
1011 * Stop playing.
1012 **************************************************************************/
1013 int libvlc_media_player_stop_async( libvlc_media_player_t *p_mi )
1015 vlc_player_t *player = p_mi->player;
1016 vlc_player_Lock(player);
1018 int ret = vlc_player_Stop(player);
1020 vlc_player_Unlock(player);
1022 return ret;
1025 int libvlc_media_player_set_renderer( libvlc_media_player_t *p_mi,
1026 libvlc_renderer_item_t *p_litem )
1028 vlc_player_t *player = p_mi->player;
1029 vlc_player_Lock(player);
1031 vlc_renderer_item_t *renderer = libvlc_renderer_item_to_vlc(p_litem);
1032 vlc_player_SetRenderer(player, renderer);
1034 vlc_player_Unlock(player);
1035 return 0;
1038 void libvlc_video_set_callbacks( libvlc_media_player_t *mp,
1039 void *(*lock_cb) (void *, void **),
1040 void (*unlock_cb) (void *, void *, void *const *),
1041 void (*display_cb) (void *, void *),
1042 void *opaque )
1044 var_SetAddress( mp, "vmem-lock", lock_cb );
1045 var_SetAddress( mp, "vmem-unlock", unlock_cb );
1046 var_SetAddress( mp, "vmem-display", display_cb );
1047 var_SetAddress( mp, "vmem-data", opaque );
1048 var_SetString( mp, "dec-dev", "none" );
1049 var_SetString( mp, "vout", "vmem" );
1050 var_SetString( mp, "window", "dummy" );
1053 void libvlc_video_set_format_callbacks( libvlc_media_player_t *mp,
1054 libvlc_video_format_cb setup,
1055 libvlc_video_cleanup_cb cleanup )
1057 var_SetAddress( mp, "vmem-setup", setup );
1058 var_SetAddress( mp, "vmem-cleanup", cleanup );
1061 void libvlc_video_set_format( libvlc_media_player_t *mp, const char *chroma,
1062 unsigned width, unsigned height, unsigned pitch )
1064 var_SetString( mp, "vmem-chroma", chroma );
1065 var_SetInteger( mp, "vmem-width", width );
1066 var_SetInteger( mp, "vmem-height", height );
1067 var_SetInteger( mp, "vmem-pitch", pitch );
1070 bool libvlc_video_set_output_callbacks(libvlc_media_player_t *mp,
1071 libvlc_video_engine_t engine,
1072 libvlc_video_output_setup_cb setup_cb,
1073 libvlc_video_output_cleanup_cb cleanup_cb,
1074 libvlc_video_output_set_resize_cb resize_cb,
1075 libvlc_video_update_output_cb update_output_cb,
1076 libvlc_video_swap_cb swap_cb,
1077 libvlc_video_makeCurrent_cb makeCurrent_cb,
1078 libvlc_video_getProcAddress_cb getProcAddress_cb,
1079 libvlc_video_frameMetadata_cb metadata_cb,
1080 libvlc_video_output_select_plane_cb select_plane_cb,
1081 void *opaque)
1083 static_assert(libvlc_video_engine_disable == 0, "No engine set must default to 0");
1084 #ifdef __ANDROID__
1085 //use the default android window
1086 var_SetString( mp, "window", "");
1087 #else
1088 var_SetString( mp, "window", "wextern");
1089 #endif
1091 if( engine == libvlc_video_engine_gles2 )
1093 var_SetString ( mp, "vout", "gles2" );
1094 var_SetString ( mp, "gles2", "vgl" );
1096 else if( engine == libvlc_video_engine_opengl )
1098 var_SetString ( mp, "vout", "gl" );
1099 var_SetString ( mp, "gl", "vgl");
1101 else if ( engine == libvlc_video_engine_d3d11 )
1103 var_SetString ( mp, "vout", "direct3d11" );
1104 var_SetString ( mp, "dec-dev", "d3d11" );
1106 else if ( engine == libvlc_video_engine_d3d9 )
1108 var_SetString ( mp, "vout", "direct3d9" );
1109 var_SetString ( mp, "dec-dev", "d3d9" );
1111 else if ( engine == libvlc_video_engine_disable )
1113 // use the default display module
1114 var_SetString ( mp, "vout", "" );
1115 // use the default window
1116 var_SetString( mp, "window", "");
1118 else
1119 return false;
1121 var_SetInteger( mp, "vout-cb-type", engine );
1122 var_SetAddress( mp, "vout-cb-opaque", opaque );
1123 var_SetAddress( mp, "vout-cb-setup", setup_cb );
1124 var_SetAddress( mp, "vout-cb-cleanup", cleanup_cb );
1125 var_SetAddress( mp, "vout-cb-resize-cb", resize_cb );
1126 var_SetAddress( mp, "vout-cb-update-output", update_output_cb );
1127 var_SetAddress( mp, "vout-cb-swap", swap_cb );
1128 var_SetAddress( mp, "vout-cb-get-proc-address", getProcAddress_cb );
1129 var_SetAddress( mp, "vout-cb-make-current", makeCurrent_cb );
1130 var_SetAddress( mp, "vout-cb-metadata", metadata_cb );
1131 var_SetAddress( mp, "vout-cb-select-plane", select_plane_cb );
1132 return true;
1135 /**************************************************************************
1136 * set_nsobject
1137 **************************************************************************/
1138 void libvlc_media_player_set_nsobject( libvlc_media_player_t *p_mi,
1139 void * drawable )
1141 assert (p_mi != NULL);
1142 #ifdef __APPLE__
1143 var_SetString (p_mi, "dec-dev", "");
1144 var_SetString (p_mi, "vout", "");
1145 var_SetString (p_mi, "window", "");
1146 var_SetAddress (p_mi, "drawable-nsobject", drawable);
1147 #else
1148 (void)drawable;
1149 libvlc_printerr ("can't set nsobject: APPLE build required");
1150 assert(false);
1151 var_SetString (p_mi, "vout", "none");
1152 var_SetString (p_mi, "window", "none");
1153 #endif
1156 /**************************************************************************
1157 * get_nsobject
1158 **************************************************************************/
1159 void * libvlc_media_player_get_nsobject( libvlc_media_player_t *p_mi )
1161 assert (p_mi != NULL);
1162 #ifdef __APPLE__
1163 return var_GetAddress (p_mi, "drawable-nsobject");
1164 #else
1165 (void) p_mi;
1166 return NULL;
1167 #endif
1170 /**************************************************************************
1171 * set_xwindow
1172 **************************************************************************/
1173 void libvlc_media_player_set_xwindow( libvlc_media_player_t *p_mi,
1174 uint32_t drawable )
1176 assert (p_mi != NULL);
1178 var_SetString (p_mi, "dec-dev", "");
1179 var_SetString (p_mi, "vout", "");
1180 var_SetString (p_mi, "window", drawable ? "embed-xid,any" : "");
1181 var_SetInteger (p_mi, "drawable-xid", drawable);
1184 /**************************************************************************
1185 * get_xwindow
1186 **************************************************************************/
1187 uint32_t libvlc_media_player_get_xwindow( libvlc_media_player_t *p_mi )
1189 return var_GetInteger (p_mi, "drawable-xid");
1192 /**************************************************************************
1193 * set_hwnd
1194 **************************************************************************/
1195 void libvlc_media_player_set_hwnd( libvlc_media_player_t *p_mi,
1196 void *drawable )
1198 assert (p_mi != NULL);
1199 #if defined (_WIN32) || defined (__OS2__)
1200 var_SetString (p_mi, "dec-dev", "");
1201 var_SetString (p_mi, "vout", "");
1202 var_SetString (p_mi, "window",
1203 (drawable != NULL) ? "embed-hwnd,any" : "");
1204 var_SetInteger (p_mi, "drawable-hwnd", (uintptr_t)drawable);
1205 #else
1206 (void) drawable;
1207 libvlc_printerr ("can't set hwnd: WIN32 build required");
1208 assert(false);
1209 var_SetString (p_mi, "vout", "none");
1210 var_SetString (p_mi, "window", "none");
1211 #endif
1214 /**************************************************************************
1215 * get_hwnd
1216 **************************************************************************/
1217 void *libvlc_media_player_get_hwnd( libvlc_media_player_t *p_mi )
1219 assert (p_mi != NULL);
1220 #if defined (_WIN32) || defined (__OS2__)
1221 return (void *)(uintptr_t)var_GetInteger (p_mi, "drawable-hwnd");
1222 #else
1223 (void) p_mi;
1224 return NULL;
1225 #endif
1228 /**************************************************************************
1229 * set_android_context
1230 **************************************************************************/
1231 void libvlc_media_player_set_android_context( libvlc_media_player_t *p_mi,
1232 void *p_awindow_handler )
1234 assert (p_mi != NULL);
1235 #ifdef __ANDROID__
1236 var_SetAddress (p_mi, "drawable-androidwindow", p_awindow_handler);
1237 #else
1238 (void) p_awindow_handler;
1239 libvlc_printerr ("can't set android context: ANDROID build required");
1240 assert(false);
1241 var_SetString (p_mi, "vout", "none");
1242 var_SetString (p_mi, "window", "none");
1243 #endif
1246 void libvlc_audio_set_callbacks( libvlc_media_player_t *mp,
1247 libvlc_audio_play_cb play_cb,
1248 libvlc_audio_pause_cb pause_cb,
1249 libvlc_audio_resume_cb resume_cb,
1250 libvlc_audio_flush_cb flush_cb,
1251 libvlc_audio_drain_cb drain_cb,
1252 void *opaque )
1254 var_SetAddress( mp, "amem-play", play_cb );
1255 var_SetAddress( mp, "amem-pause", pause_cb );
1256 var_SetAddress( mp, "amem-resume", resume_cb );
1257 var_SetAddress( mp, "amem-flush", flush_cb );
1258 var_SetAddress( mp, "amem-drain", drain_cb );
1259 var_SetAddress( mp, "amem-data", opaque );
1260 var_SetString( mp, "aout", "amem,none" );
1262 vlc_player_aout_Reset( mp->player );
1265 void libvlc_audio_set_volume_callback( libvlc_media_player_t *mp,
1266 libvlc_audio_set_volume_cb cb )
1268 var_SetAddress( mp, "amem-set-volume", cb );
1270 vlc_player_aout_Reset( mp->player );
1273 void libvlc_audio_set_format_callbacks( libvlc_media_player_t *mp,
1274 libvlc_audio_setup_cb setup,
1275 libvlc_audio_cleanup_cb cleanup )
1277 var_SetAddress( mp, "amem-setup", setup );
1278 var_SetAddress( mp, "amem-cleanup", cleanup );
1280 vlc_player_aout_Reset( mp->player );
1283 void libvlc_audio_set_format( libvlc_media_player_t *mp, const char *format,
1284 unsigned rate, unsigned channels )
1286 var_SetString( mp, "amem-format", format );
1287 var_SetInteger( mp, "amem-rate", rate );
1288 var_SetInteger( mp, "amem-channels", channels );
1290 vlc_player_aout_Reset( mp->player );
1294 /**************************************************************************
1295 * Getters for stream information
1296 **************************************************************************/
1297 libvlc_time_t libvlc_media_player_get_length(
1298 libvlc_media_player_t *p_mi )
1300 vlc_player_t *player = p_mi->player;
1301 vlc_player_Lock(player);
1303 vlc_tick_t length = vlc_player_GetLength(player);
1304 libvlc_time_t i_time = from_mtime(length);
1306 vlc_player_Unlock(player);
1307 return i_time;
1310 libvlc_time_t libvlc_media_player_get_time( libvlc_media_player_t *p_mi )
1312 vlc_player_t *player = p_mi->player;
1313 vlc_player_Lock(player);
1315 vlc_tick_t tick = vlc_player_GetTime(player);
1316 libvlc_time_t i_time = from_mtime(tick);
1318 vlc_player_Unlock(player);
1319 return i_time;
1322 int libvlc_media_player_set_time( libvlc_media_player_t *p_mi,
1323 libvlc_time_t i_time, bool b_fast )
1325 vlc_tick_t tick = to_mtime(i_time);
1327 vlc_player_t *player = p_mi->player;
1328 vlc_player_Lock(player);
1330 enum vlc_player_seek_speed speed = b_fast ? VLC_PLAYER_SEEK_FAST
1331 : VLC_PLAYER_SEEK_PRECISE;
1332 vlc_player_SeekByTime(player, tick, speed, VLC_PLAYER_WHENCE_ABSOLUTE);
1334 vlc_player_Unlock(player);
1336 /* may not fail anymore, keep int not to break the API */
1337 return 0;
1340 int libvlc_media_player_set_position( libvlc_media_player_t *p_mi,
1341 float position, bool b_fast )
1343 vlc_player_t *player = p_mi->player;
1344 vlc_player_Lock(player);
1346 enum vlc_player_seek_speed speed = b_fast ? VLC_PLAYER_SEEK_FAST
1347 : VLC_PLAYER_SEEK_PRECISE;
1348 vlc_player_SeekByPos(player, position, speed, VLC_PLAYER_WHENCE_ABSOLUTE);
1350 vlc_player_Unlock(player);
1352 /* may not fail anymore, keep int not to break the API */
1353 return 0;
1356 float libvlc_media_player_get_position( libvlc_media_player_t *p_mi )
1358 vlc_player_t *player = p_mi->player;
1359 vlc_player_Lock(player);
1361 float f_position = vlc_player_GetPosition(player);
1363 vlc_player_Unlock(player);
1364 return f_position;
1367 void libvlc_media_player_set_chapter( libvlc_media_player_t *p_mi,
1368 int chapter )
1370 vlc_player_t *player = p_mi->player;
1371 vlc_player_Lock(player);
1373 vlc_player_SelectChapterIdx(player, chapter);
1375 vlc_player_Unlock(player);
1378 int libvlc_media_player_get_chapter( libvlc_media_player_t *p_mi )
1380 vlc_player_t *player = p_mi->player;
1381 vlc_player_Lock(player);
1383 ssize_t i_chapter = vlc_player_GetSelectedChapterIdx(player);
1385 vlc_player_Unlock(player);
1386 return i_chapter;
1389 int libvlc_media_player_get_chapter_count( libvlc_media_player_t *p_mi )
1391 vlc_player_t *player = p_mi->player;
1392 vlc_player_Lock(player);
1394 const struct vlc_player_title *title = vlc_player_GetSelectedTitle(player);
1395 int ret = title ? (int) title->chapter_count : -1;
1397 vlc_player_Unlock(player);
1398 return ret;
1401 int libvlc_media_player_get_chapter_count_for_title(
1402 libvlc_media_player_t *p_mi,
1403 int i_title )
1405 assert(i_title >= 0);
1406 size_t idx = i_title;
1407 int ret = -1;
1409 vlc_player_t *player = p_mi->player;
1410 vlc_player_Lock(player);
1412 vlc_player_title_list *titles = vlc_player_GetTitleList(player);
1413 if (!titles)
1414 goto end;
1416 size_t titles_count = vlc_player_title_list_GetCount(titles);
1417 if (idx < titles_count)
1418 goto end;
1420 const struct vlc_player_title *title =
1421 vlc_player_title_list_GetAt(titles, idx);
1422 assert(title);
1424 ret = title->chapter_count;
1426 end:
1427 vlc_player_Unlock(player);
1428 return ret;
1431 void libvlc_media_player_set_title( libvlc_media_player_t *p_mi,
1432 int i_title )
1434 vlc_player_t *player = p_mi->player;
1435 vlc_player_Lock(player);
1437 vlc_player_SelectTitleIdx(player, i_title);
1439 vlc_player_Unlock(player);
1442 int libvlc_media_player_get_title( libvlc_media_player_t *p_mi )
1444 vlc_player_t *player = p_mi->player;
1445 vlc_player_Lock(player);
1447 ssize_t i_title = vlc_player_GetSelectedTitleIdx(player);
1449 vlc_player_Unlock(player);
1450 return i_title;
1453 int libvlc_media_player_get_title_count( libvlc_media_player_t *p_mi )
1455 vlc_player_t *player = p_mi->player;
1456 vlc_player_Lock(player);
1458 vlc_player_title_list *titles = vlc_player_GetTitleList(player);
1459 int ret = titles ? (int) vlc_player_title_list_GetCount(titles) : -1;
1461 vlc_player_Unlock(player);
1462 return ret;
1465 int libvlc_media_player_get_full_title_descriptions( libvlc_media_player_t *p_mi,
1466 libvlc_title_description_t *** pp_titles )
1468 assert( p_mi );
1470 int ret = -1;
1472 vlc_player_t *player = p_mi->player;
1473 vlc_player_Lock(player);
1475 vlc_player_title_list *titles = vlc_player_GetTitleList(player);
1476 if (!titles)
1477 goto end;
1479 size_t count = vlc_player_title_list_GetCount(titles);
1481 libvlc_title_description_t **descs = vlc_alloc(count, sizeof(*descs));
1482 if (count > 0 && !descs)
1483 goto end;
1485 for (size_t i = 0; i < count; i++)
1487 const struct vlc_player_title *title =
1488 vlc_player_title_list_GetAt(titles, i);
1489 libvlc_title_description_t *desc = malloc(sizeof(*desc));
1490 if (!desc)
1492 libvlc_title_descriptions_release(descs, i);
1493 goto end;
1496 descs[i] = desc;
1498 /* we want to return milliseconds to match the rest of the API */
1499 desc->i_duration = MS_FROM_VLC_TICK(title->length);
1500 desc->i_flags = title->flags;
1501 desc->psz_name = title->name ? strdup(title->name) : NULL;
1504 ret = count;
1505 *pp_titles = descs;
1507 end:
1508 vlc_player_Unlock(player);
1509 return ret;
1512 void libvlc_title_descriptions_release( libvlc_title_description_t **p_titles,
1513 unsigned i_count )
1515 for (unsigned i = 0; i < i_count; i++ )
1517 if ( !p_titles[i] )
1518 continue;
1520 free( p_titles[i]->psz_name );
1521 free( p_titles[i] );
1523 free( p_titles );
1526 int libvlc_media_player_get_full_chapter_descriptions( libvlc_media_player_t *p_mi,
1527 int i_chapters_of_title,
1528 libvlc_chapter_description_t *** pp_chapters )
1530 assert( p_mi );
1532 int ret = -1;
1534 vlc_player_t *player = p_mi->player;
1535 vlc_player_Lock(player);
1537 vlc_player_title_list *titles = vlc_player_GetTitleList(player);
1538 if (!titles)
1539 goto end;
1541 size_t titles_count = vlc_player_title_list_GetCount(titles);
1542 if (i_chapters_of_title < (int) titles_count)
1543 goto end;
1545 const struct vlc_player_title *title =
1546 vlc_player_title_list_GetAt(titles, i_chapters_of_title);
1547 assert(title);
1549 size_t i_chapter_count = title->chapter_count;
1551 libvlc_chapter_description_t **descs =
1552 vlc_alloc(i_chapter_count, sizeof(*descs));
1553 if (i_chapter_count > 0 && !descs)
1554 goto end;
1556 for (size_t i = 0; i < i_chapter_count; i++)
1558 const struct vlc_player_chapter *chapter = &title->chapters[i];
1559 libvlc_chapter_description_t *desc = malloc(sizeof(*desc));
1560 if (!desc)
1562 libvlc_chapter_descriptions_release(descs, i);
1563 goto end;
1566 descs[i] = desc;
1568 vlc_tick_t chapter_end = i < i_chapter_count - 1
1569 ? title->chapters[i + 1].time
1570 : title->length;
1571 desc->i_time_offset = MS_FROM_VLC_TICK(chapter->time);
1572 desc->psz_name = chapter->name ? strdup(chapter->name) : NULL;
1573 desc->i_duration = MS_FROM_VLC_TICK(chapter_end) - desc->i_time_offset;
1576 ret = i_chapter_count;
1577 *pp_chapters = descs;
1579 end:
1580 vlc_player_Unlock(player);
1581 return ret;
1584 void libvlc_chapter_descriptions_release( libvlc_chapter_description_t **p_chapters,
1585 unsigned i_count )
1587 for (unsigned i = 0; i < i_count; i++ )
1589 if ( !p_chapters[i] )
1590 continue;
1592 free( p_chapters[i]->psz_name );
1593 free( p_chapters[i] );
1595 free( p_chapters );
1598 void libvlc_media_player_next_chapter( libvlc_media_player_t *p_mi )
1600 vlc_player_t *player = p_mi->player;
1601 vlc_player_Lock(player);
1603 vlc_player_SelectNextChapter(player);
1605 vlc_player_Unlock(player);
1608 void libvlc_media_player_previous_chapter( libvlc_media_player_t *p_mi )
1610 vlc_player_t *player = p_mi->player;
1611 vlc_player_Lock(player);
1613 vlc_player_SelectPrevChapter(player);
1615 vlc_player_Unlock(player);
1618 int libvlc_media_player_set_rate( libvlc_media_player_t *p_mi, float rate )
1620 vlc_player_t *player = p_mi->player;
1621 vlc_player_Lock(player);
1623 vlc_player_ChangeRate(player, rate);
1625 vlc_player_Unlock(player);
1626 return 0;
1629 float libvlc_media_player_get_rate( libvlc_media_player_t *p_mi )
1631 vlc_player_t *player = p_mi->player;
1632 vlc_player_Lock(player);
1634 float rate = vlc_player_GetRate(player);
1636 vlc_player_Unlock(player);
1637 return rate;
1640 libvlc_state_t libvlc_media_player_get_state( libvlc_media_player_t *p_mi )
1642 vlc_player_t *player = p_mi->player;
1643 vlc_player_Lock(player);
1645 enum vlc_player_error error = vlc_player_GetError(player);
1646 enum vlc_player_state state = vlc_player_GetState(player);
1648 vlc_player_Unlock(player);
1650 if (error != VLC_PLAYER_ERROR_NONE)
1651 return libvlc_Error;
1652 switch (state) {
1653 case VLC_PLAYER_STATE_STOPPED:
1654 return libvlc_Stopped;
1655 case VLC_PLAYER_STATE_STOPPING:
1656 return libvlc_Ended;
1657 case VLC_PLAYER_STATE_STARTED:
1658 return libvlc_Opening;
1659 case VLC_PLAYER_STATE_PLAYING:
1660 return libvlc_Playing;
1661 case VLC_PLAYER_STATE_PAUSED:
1662 return libvlc_Paused;
1663 default:
1664 vlc_assert_unreachable();
1668 bool libvlc_media_player_is_seekable(libvlc_media_player_t *p_mi)
1670 vlc_player_t *player = p_mi->player;
1671 vlc_player_Lock(player);
1673 bool b_seekable = vlc_player_CanSeek(player);
1675 vlc_player_Unlock(player);
1676 return b_seekable;
1679 void libvlc_media_player_navigate( libvlc_media_player_t* p_mi,
1680 unsigned navigate )
1682 static const enum vlc_player_nav map[] =
1684 VLC_PLAYER_NAV_ACTIVATE, VLC_PLAYER_NAV_UP, VLC_PLAYER_NAV_DOWN,
1685 VLC_PLAYER_NAV_LEFT, VLC_PLAYER_NAV_RIGHT, VLC_PLAYER_NAV_POPUP,
1688 if( navigate >= sizeof(map) / sizeof(map[0]) )
1689 return;
1691 vlc_player_t *player = p_mi->player;
1692 vlc_player_Lock(player);
1694 vlc_player_Navigate(player, map[navigate]);
1696 vlc_player_Unlock(player);
1699 /* internal function, used by audio, video */
1700 libvlc_track_description_t *
1701 libvlc_get_track_description( libvlc_media_player_t *p_mi,
1702 enum es_format_category_e cat )
1704 vlc_player_t *player = p_mi->player;
1705 vlc_player_Lock(player);
1707 libvlc_track_description_t *ret, **pp = &ret;
1709 size_t count = vlc_player_GetTrackCount(player, cat);
1710 for (size_t i = 0; i < count; i++)
1712 libvlc_track_description_t *tr = malloc(sizeof (*tr));
1713 if (unlikely(tr == NULL))
1715 libvlc_printerr("Not enough memory");
1716 continue;
1719 const struct vlc_player_track *track =
1720 vlc_player_GetTrackAt(player, cat, i);
1722 *pp = tr;
1723 tr->i_id = vlc_es_id_GetInputId(track->es_id);
1724 tr->psz_name = strdup(track->name);
1725 if (unlikely(!tr->psz_name))
1727 free(tr);
1728 continue;
1730 pp = &tr->p_next;
1733 *pp = NULL;
1735 vlc_player_Unlock(player);
1736 return ret;
1739 void libvlc_track_description_list_release( libvlc_track_description_t *p_td )
1741 libvlc_track_description_t *p_actual, *p_before;
1742 p_actual = p_td;
1744 while ( p_actual )
1746 free( p_actual->psz_name );
1747 p_before = p_actual;
1748 p_actual = p_before->p_next;
1749 free( p_before );
1753 bool libvlc_media_player_can_pause(libvlc_media_player_t *p_mi)
1755 vlc_player_t *player = p_mi->player;
1756 vlc_player_Lock(player);
1758 bool b_can_pause = vlc_player_CanPause(player);
1760 vlc_player_Unlock(player);
1761 return b_can_pause;
1764 bool libvlc_media_player_program_scrambled(libvlc_media_player_t *p_mi)
1766 bool b_program_scrambled = false;
1768 vlc_player_t *player = p_mi->player;
1769 vlc_player_Lock(player);
1771 const struct vlc_player_program *program =
1772 vlc_player_GetSelectedProgram(player);
1773 if (!program)
1774 goto end;
1776 b_program_scrambled = program->scrambled;
1778 vlc_player_Unlock(player);
1779 end:
1780 return b_program_scrambled;
1783 void libvlc_media_player_next_frame( libvlc_media_player_t *p_mi )
1785 vlc_player_t *player = p_mi->player;
1786 vlc_player_Lock(player);
1788 vlc_player_NextVideoFrame(player);
1790 vlc_player_Unlock(player);
1794 * Private lookup table to get subpicture alignment flag values corresponding
1795 * to a libvlc_position_t enumerated value.
1797 static const unsigned char position_subpicture_alignment[] = {
1798 [libvlc_position_center] = 0,
1799 [libvlc_position_left] = SUBPICTURE_ALIGN_LEFT,
1800 [libvlc_position_right] = SUBPICTURE_ALIGN_RIGHT,
1801 [libvlc_position_top] = SUBPICTURE_ALIGN_TOP,
1802 [libvlc_position_top_left] = SUBPICTURE_ALIGN_TOP | SUBPICTURE_ALIGN_LEFT,
1803 [libvlc_position_top_right] = SUBPICTURE_ALIGN_TOP | SUBPICTURE_ALIGN_RIGHT,
1804 [libvlc_position_bottom] = SUBPICTURE_ALIGN_BOTTOM,
1805 [libvlc_position_bottom_left] = SUBPICTURE_ALIGN_BOTTOM | SUBPICTURE_ALIGN_LEFT,
1806 [libvlc_position_bottom_right] = SUBPICTURE_ALIGN_BOTTOM | SUBPICTURE_ALIGN_RIGHT
1809 void libvlc_media_player_set_video_title_display( libvlc_media_player_t *p_mi, libvlc_position_t position, unsigned timeout )
1811 assert( position >= libvlc_position_disable && position <= libvlc_position_bottom_right );
1813 if ( position != libvlc_position_disable )
1815 var_SetBool( p_mi, "video-title-show", true );
1816 var_SetInteger( p_mi, "video-title-position", position_subpicture_alignment[position] );
1817 var_SetInteger( p_mi, "video-title-timeout", timeout );
1819 else
1821 var_SetBool( p_mi, "video-title-show", false );
1825 libvlc_media_tracklist_t *
1826 libvlc_media_player_get_tracklist(libvlc_media_player_t *p_mi,
1827 libvlc_track_type_t type)
1829 vlc_player_t *player = p_mi->player;
1831 vlc_player_Lock(player);
1833 libvlc_media_tracklist_t *list =
1834 libvlc_media_tracklist_from_player(player, type);
1836 vlc_player_Unlock(player);
1838 return list;
1841 libvlc_media_track_t *
1842 libvlc_media_player_get_selected_track(libvlc_media_player_t *p_mi,
1843 libvlc_track_type_t type)
1845 vlc_player_t *player = p_mi->player;
1847 vlc_player_Lock(player);
1849 const enum es_format_category_e cat = libvlc_track_type_to_escat(type);
1850 const struct vlc_player_track *track =
1851 vlc_player_GetSelectedTrack(player, cat);
1853 if (track == NULL)
1855 vlc_player_Unlock(player);
1856 return NULL;
1859 libvlc_media_track_t *libtrack =
1860 libvlc_media_track_create_from_player_track(track);
1861 vlc_player_Unlock(player);
1863 return libtrack;
1866 libvlc_media_track_t *
1867 libvlc_media_player_get_track_from_id( libvlc_media_player_t *p_mi,
1868 const char *psz_id )
1870 vlc_player_t *player = p_mi->player;
1872 vlc_player_Lock(player);
1874 enum es_format_category_e cats[] = { VIDEO_ES, AUDIO_ES, SPU_ES };
1875 for (size_t i = 0; i < ARRAY_SIZE(cats); ++i)
1877 enum es_format_category_e cat = cats[i];
1878 size_t count = vlc_player_GetTrackCount(player, cat);
1880 for (size_t j = 0; j < count; ++j)
1882 const struct vlc_player_track *track =
1883 vlc_player_GetTrackAt(player, cat, j);
1884 if (strcmp(psz_id, vlc_es_id_GetStrId(track->es_id)) == 0)
1886 libvlc_media_track_t *libtrack =
1887 libvlc_media_track_create_from_player_track(track);
1888 vlc_player_Unlock(player);
1889 return libtrack;
1895 vlc_player_Unlock(player);
1896 return NULL;
1899 void
1900 libvlc_media_player_select_track(libvlc_media_player_t *p_mi,
1901 libvlc_track_type_t type,
1902 const libvlc_media_track_t *track)
1904 assert( track == NULL || type == track->i_type );
1905 vlc_player_t *player = p_mi->player;
1907 vlc_player_Lock(player);
1909 if (track != NULL)
1911 const libvlc_media_trackpriv_t *trackpriv =
1912 libvlc_media_track_to_priv(track);
1913 vlc_player_SelectEsId(player, trackpriv->es_id,
1914 VLC_PLAYER_SELECT_EXCLUSIVE);
1916 else
1918 const enum es_format_category_e cat = libvlc_track_type_to_escat(type);
1919 vlc_player_UnselectTrackCategory(player, cat);
1922 vlc_player_Unlock(player);
1925 void
1926 libvlc_media_player_select_tracks(libvlc_media_player_t *p_mi,
1927 libvlc_track_type_t type,
1928 const libvlc_media_track_t **tracks,
1929 size_t track_count)
1931 vlc_player_t *player = p_mi->player;
1933 vlc_es_id_t **es_id_list = vlc_alloc(track_count + 1, sizeof(vlc_es_id_t *));
1934 size_t es_id_idx = 0;
1936 if (es_id_list == NULL)
1937 return;
1939 const enum es_format_category_e cat = libvlc_track_type_to_escat(type);
1941 vlc_player_Lock(player);
1943 for (size_t i = 0; i < track_count; ++i)
1945 const libvlc_media_track_t *track = tracks[i];
1946 const libvlc_media_trackpriv_t *trackpriv =
1947 libvlc_media_track_to_priv(track);
1949 es_id_list[es_id_idx++] = trackpriv->es_id;
1951 es_id_list[es_id_idx++] = NULL;
1952 vlc_player_SelectEsIdList(player, cat, es_id_list);
1954 vlc_player_Unlock(player);
1956 free(es_id_list);
1959 void
1960 libvlc_media_player_select_tracks_by_ids( libvlc_media_player_t *p_mi,
1961 libvlc_track_type_t type,
1962 const char *psz_ids )
1964 const enum es_format_category_e cat = libvlc_track_type_to_escat(type);
1966 vlc_player_t *player = p_mi->player;
1968 vlc_player_Lock(player);
1970 vlc_player_SelectTracksByStringIds(player, cat, psz_ids);
1972 vlc_player_Unlock(player);
1975 int libvlc_media_player_add_slave( libvlc_media_player_t *p_mi,
1976 libvlc_media_slave_type_t i_type,
1977 const char *psz_uri, bool b_select )
1979 vlc_player_t *player = p_mi->player;
1980 vlc_player_Lock(player);
1982 enum es_format_category_e cat = i_type == libvlc_media_slave_type_subtitle
1983 ? SPU_ES
1984 : AUDIO_ES;
1986 int ret = vlc_player_AddAssociatedMedia(player, cat, psz_uri, b_select,
1987 false, false);
1989 vlc_player_Unlock(player);
1990 return ret;
1994 * Maximum size of a formatted equalizer amplification band frequency value.
1996 * The allowed value range is supposed to be constrained from -20.0 to 20.0.
1998 * The format string " %.07f" with a minimum value of "-20" gives a maximum
1999 * string length of e.g. " -19.1234567", i.e. 12 bytes (not including the null
2000 * terminator).
2002 #define EQZ_BAND_VALUE_SIZE 12
2004 int libvlc_media_player_set_equalizer( libvlc_media_player_t *p_mi, libvlc_equalizer_t *p_equalizer )
2006 char bands[EQZ_BANDS_MAX * EQZ_BAND_VALUE_SIZE + 1];
2008 if( p_equalizer != NULL )
2010 for( unsigned i = 0, c = 0; i < EQZ_BANDS_MAX; i++ )
2012 c += snprintf( bands + c, sizeof(bands) - c, " %.07f",
2013 p_equalizer->f_amp[i] );
2014 if( unlikely(c >= sizeof(bands)) )
2015 return -1;
2018 var_SetFloat( p_mi, "equalizer-preamp", p_equalizer->f_preamp );
2019 var_SetString( p_mi, "equalizer-bands", bands );
2021 var_SetString( p_mi, "audio-filter", p_equalizer ? "equalizer" : "" );
2023 audio_output_t *p_aout = vlc_player_aout_Hold( p_mi->player );
2024 if( p_aout != NULL )
2026 if( p_equalizer != NULL )
2028 var_SetFloat( p_aout, "equalizer-preamp", p_equalizer->f_preamp );
2029 var_SetString( p_aout, "equalizer-bands", bands );
2032 var_SetString( p_aout, "audio-filter", p_equalizer ? "equalizer" : "" );
2033 aout_Release(p_aout);
2036 return 0;
2039 static const char roles[][16] =
2041 [libvlc_role_Music] = "music",
2042 [libvlc_role_Video] = "video",
2043 [libvlc_role_Communication] = "communication",
2044 [libvlc_role_Game] = "game",
2045 [libvlc_role_Notification] = "notification",
2046 [libvlc_role_Animation] = "animation",
2047 [libvlc_role_Production] = "production",
2048 [libvlc_role_Accessibility] = "accessibility",
2049 [libvlc_role_Test] = "test",
2052 int libvlc_media_player_set_role(libvlc_media_player_t *mp, unsigned role)
2054 if (role >= ARRAY_SIZE(roles)
2055 || var_SetString(mp, "role", roles[role]) != VLC_SUCCESS)
2056 return -1;
2057 return 0;
2060 int libvlc_media_player_get_role(libvlc_media_player_t *mp)
2062 int ret = -1;
2063 char *str = var_GetString(mp, "role");
2064 if (str == NULL)
2065 return 0;
2067 for (size_t i = 0; i < ARRAY_SIZE(roles); i++)
2068 if (!strcmp(roles[i], str))
2070 ret = i;
2071 break;
2074 free(str);
2075 return ret;
2078 #include <vlc_vout_display.h>
2080 /* make sure surface structures from libvlc can be passed as such to vlc
2081 otherwise we will need wrappers between what libvlc understands and what vlc uses */
2082 #define cast_ libvlc_video_color_space_t
2083 static_assert(libvlc_video_colorspace_BT601 == (cast_)COLOR_SPACE_BT601 &&
2084 libvlc_video_colorspace_BT709 == (cast_)COLOR_SPACE_BT709 &&
2085 libvlc_video_colorspace_BT2020 == (cast_)COLOR_SPACE_BT2020
2086 , "libvlc video colorspace mismatch");
2087 #undef cast_
2089 #define cast_ libvlc_video_transfer_func_t
2090 static_assert(libvlc_video_transfer_func_LINEAR == (cast_)TRANSFER_FUNC_LINEAR &&
2091 libvlc_video_transfer_func_SRGB == (cast_)TRANSFER_FUNC_SRGB &&
2092 libvlc_video_transfer_func_BT470_BG == (cast_)TRANSFER_FUNC_BT470_BG &&
2093 libvlc_video_transfer_func_BT470_M == (cast_)TRANSFER_FUNC_BT470_M &&
2094 libvlc_video_transfer_func_BT709 == (cast_)TRANSFER_FUNC_BT709 &&
2095 libvlc_video_transfer_func_PQ == (cast_)TRANSFER_FUNC_SMPTE_ST2084 &&
2096 libvlc_video_transfer_func_SMPTE_240 == (cast_)TRANSFER_FUNC_SMPTE_240 &&
2097 libvlc_video_transfer_func_HLG == (cast_)TRANSFER_FUNC_HLG
2098 , "libvlc video transfer function mismatch");
2099 #undef cast_
2101 #define cast_ libvlc_video_color_primaries_t
2102 static_assert(libvlc_video_primaries_BT601_525 == (cast_)COLOR_PRIMARIES_BT601_525 &&
2103 libvlc_video_primaries_BT601_625 == (cast_)COLOR_PRIMARIES_BT601_625 &&
2104 libvlc_video_primaries_BT709 == (cast_)COLOR_PRIMARIES_BT709 &&
2105 libvlc_video_primaries_BT2020 == (cast_)COLOR_PRIMARIES_BT2020 &&
2106 libvlc_video_primaries_DCI_P3 == (cast_)COLOR_PRIMARIES_DCI_P3 &&
2107 libvlc_video_primaries_BT470_M == (cast_)COLOR_PRIMARIES_BT470_M
2108 , "libvlc video color primaries mismatch");
2109 #undef cast_