qml: provide modal dialogs instantiable from QML
[vlc.git] / lib / media_player.c
blob1b736da12e4623216cf490cf2ecc738451c6d9fd
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 if (action == VLC_PLAYER_LIST_ADDED)
255 event.type = libvlc_MediaPlayerESAdded;
256 else if (action == VLC_PLAYER_LIST_REMOVED)
257 event.type = libvlc_MediaPlayerESDeleted;
258 else
259 /* no event to forward */
260 return;
262 event.u.media_player_es_changed.i_type =
263 track_type_from_cat(track->fmt.i_cat);
264 event.u.media_player_es_changed.i_id = vlc_es_id_GetInputId(track->es_id);
266 libvlc_event_send(&mp->event_manager, &event);
269 static void
270 on_track_selection_changed(vlc_player_t *player, vlc_es_id_t *unselected_id,
271 vlc_es_id_t *selected_id, void *data)
273 (void) player;
274 (void) unselected_id;
276 libvlc_media_player_t *mp = data;
278 libvlc_event_t event;
279 event.type = libvlc_MediaPlayerESSelected;
281 if (selected_id)
283 enum es_format_category_e cat = vlc_es_id_GetCat(selected_id);
284 event.u.media_player_es_changed.i_type = track_type_from_cat(cat);
285 event.u.media_player_es_changed.i_id =
286 vlc_es_id_GetInputId(selected_id);
287 libvlc_event_send(&mp->event_manager, &event);
291 static void
292 on_program_list_changed(vlc_player_t *player,
293 enum vlc_player_list_action action,
294 const struct vlc_player_program *prgm, void* data)
296 (void) action;
297 (void) prgm;
299 libvlc_media_player_t *mp = data;
301 const struct vlc_player_program *selected =
302 vlc_player_GetSelectedProgram(player);
303 if (!selected)
304 return;
306 libvlc_event_t event;
307 event.type = libvlc_MediaPlayerScrambledChanged;
308 event.u.media_player_scrambled_changed.new_scrambled = selected->scrambled;
310 libvlc_event_send(&mp->event_manager, &event);
313 static void
314 on_program_selection_changed(vlc_player_t *player, int unselected_id,
315 int selected_id, void *data)
317 (void) unselected_id;
319 libvlc_media_player_t *mp = data;
321 if (selected_id == -1)
322 return;
324 const struct vlc_player_program *program =
325 vlc_player_GetSelectedProgram(player);
326 assert(program);
328 libvlc_event_t event;
329 event.type = libvlc_MediaPlayerScrambledChanged;
330 event.u.media_player_scrambled_changed.new_scrambled = program->scrambled;
332 libvlc_event_send(&mp->event_manager, &event);
335 static void
336 on_title_selection_changed(vlc_player_t *player,
337 const struct vlc_player_title *new_title,
338 size_t new_idx, void *data)
340 (void) player;
341 (void) new_title;
343 libvlc_media_player_t *mp = data;
345 libvlc_event_t event;
346 event.type = libvlc_MediaPlayerTitleChanged;
347 event.u.media_player_title_changed.new_title = new_idx;
349 libvlc_event_send(&mp->event_manager, &event);
352 static void
353 on_chapter_selection_changed(vlc_player_t *player,
354 const struct vlc_player_title *title,
355 size_t title_idx,
356 const struct vlc_player_chapter *new_chapter,
357 size_t new_chapter_idx,
358 void *data)
360 (void) player;
361 (void) title;
362 (void) title_idx;
363 (void) new_chapter;
365 libvlc_media_player_t *mp = data;
367 libvlc_event_t event;
368 event.type = libvlc_MediaPlayerChapterChanged;
369 event.u.media_player_chapter_changed.new_chapter = new_chapter_idx;
371 libvlc_event_send(&mp->event_manager, &event);
374 static void
375 on_media_subitems_changed(vlc_player_t *player, input_item_t *media,
376 input_item_node_t *new_subitems, void *data)
378 (void) player;
380 libvlc_media_player_t *mp = data;
382 input_item_t *current = mp->p_md ? mp->p_md->p_input_item : NULL;
383 if (media == current)
384 libvlc_media_add_subtree(mp->p_md, new_subitems);
387 static void
388 on_cork_changed(vlc_player_t *player, unsigned cork_count, void *data)
390 (void) player;
392 libvlc_media_player_t *mp = data;
394 libvlc_event_t event;
395 event.type = cork_count ? libvlc_MediaPlayerCorked
396 : libvlc_MediaPlayerUncorked;
398 libvlc_event_send(&mp->event_manager, &event);
401 static void
402 on_vout_changed(vlc_player_t *player, enum vlc_player_vout_action action,
403 vout_thread_t *vout, enum vlc_vout_order order,
404 vlc_es_id_t *es_id, void *data)
406 (void) action;
407 (void) vout;
408 (void) order;
410 if (vlc_es_id_GetCat(es_id) != VIDEO_ES)
411 return;
413 libvlc_media_player_t *mp = data;
415 size_t count;
416 vout_thread_t **vouts = vlc_player_vout_HoldAll(player, &count);
417 if (!vouts)
418 return;
419 for (size_t i = 0; i < count; ++i)
420 vout_Release(vouts[i]);
421 free(vouts);
423 libvlc_event_t event;
424 event.type = libvlc_MediaPlayerVout;
425 event.u.media_player_vout.new_count = count;
427 libvlc_event_send(&mp->event_manager, &event);
430 // player aout callbacks
432 static void
433 on_volume_changed(audio_output_t *aout, float new_volume, void *data)
435 (void) aout;
437 libvlc_media_player_t *mp = data;
439 libvlc_event_t event;
440 event.type = libvlc_MediaPlayerAudioVolume;
441 event.u.media_player_audio_volume.volume = new_volume;
443 libvlc_event_send(&mp->event_manager, &event);
446 static void
447 on_mute_changed(audio_output_t *aout, bool new_muted, void *data)
449 (void) aout;
451 libvlc_media_player_t *mp = data;
453 libvlc_event_t event;
454 event.type = new_muted ? libvlc_MediaPlayerMuted
455 : libvlc_MediaPlayerUnmuted;
457 libvlc_event_send(&mp->event_manager, &event);
460 static void
461 on_audio_device_changed(audio_output_t *aout, const char *device, void *data)
463 (void) aout;
465 libvlc_media_player_t *mp = data;
467 libvlc_event_t event;
468 event.type = libvlc_MediaPlayerAudioDevice;
469 event.u.media_player_audio_device.device = device;
471 libvlc_event_send(&mp->event_manager, &event);
474 static const struct vlc_player_cbs vlc_player_cbs = {
475 .on_current_media_changed = on_current_media_changed,
476 .on_state_changed = on_state_changed,
477 .on_error_changed = on_error_changed,
478 .on_buffering_changed = on_buffering_changed,
479 .on_capabilities_changed = on_capabilities_changed,
480 .on_position_changed = on_position_changed,
481 .on_length_changed = on_length_changed,
482 .on_track_list_changed = on_track_list_changed,
483 .on_track_selection_changed = on_track_selection_changed,
484 .on_program_list_changed = on_program_list_changed,
485 .on_program_selection_changed = on_program_selection_changed,
486 .on_title_selection_changed = on_title_selection_changed,
487 .on_chapter_selection_changed = on_chapter_selection_changed,
488 .on_media_subitems_changed = on_media_subitems_changed,
489 .on_cork_changed = on_cork_changed,
490 .on_vout_changed = on_vout_changed,
493 static const struct vlc_player_aout_cbs vlc_player_aout_cbs = {
494 .on_volume_changed = on_volume_changed,
495 .on_mute_changed = on_mute_changed,
496 .on_device_changed = on_audio_device_changed,
499 /**************************************************************************
500 * Snapshot Taken Event.
502 * FIXME: This snapshot API interface makes no sense in media_player.
503 *************************************************************************/
504 static int snapshot_was_taken(vlc_object_t *p_this, char const *psz_cmd,
505 vlc_value_t oldval, vlc_value_t newval, void *p_data )
507 VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval); VLC_UNUSED(p_this);
509 libvlc_media_player_t *mp = p_data;
510 libvlc_event_t event;
511 event.type = libvlc_MediaPlayerSnapshotTaken;
512 event.u.media_player_snapshot_taken.psz_filename = newval.psz_string;
513 libvlc_event_send(&mp->event_manager, &event);
515 return VLC_SUCCESS;
518 static void input_item_preparsed_changed( const vlc_event_t *p_event,
519 void * user_data )
521 libvlc_media_t *p_md = user_data;
522 if( p_event->u.input_item_preparsed_changed.new_status & ITEM_PREPARSED )
524 /* Send the event */
525 libvlc_event_t event;
526 event.type = libvlc_MediaParsedChanged;
527 event.u.media_parsed_changed.new_status = libvlc_media_parsed_status_done;
528 libvlc_event_send( &p_md->event_manager, &event );
532 static void media_attach_preparsed_event( libvlc_media_t *p_md )
534 vlc_event_attach( &p_md->p_input_item->event_manager,
535 vlc_InputItemPreparsedChanged,
536 input_item_preparsed_changed, p_md );
539 static void media_detach_preparsed_event( libvlc_media_t *p_md )
541 vlc_event_detach( &p_md->p_input_item->event_manager,
542 vlc_InputItemPreparsedChanged,
543 input_item_preparsed_changed,
544 p_md );
547 /**************************************************************************
548 * Create a Media Instance object.
550 * Refcount strategy:
551 * - All items created by _new start with a refcount set to 1.
552 * - Accessor _release decrease the refcount by 1, if after that
553 * operation the refcount is 0, the object is destroyed.
554 * - Accessor _retain increase the refcount by 1 (XXX: to implement)
556 * Object locking strategy:
557 * - No lock held while in constructor.
558 * - When accessing any member variable this lock is held. (XXX who locks?)
559 * - When attempting to destroy the object the lock is also held.
560 **************************************************************************/
561 libvlc_media_player_t *
562 libvlc_media_player_new( libvlc_instance_t *instance )
564 libvlc_media_player_t * mp;
566 assert(instance);
568 mp = vlc_object_create (instance->p_libvlc_int, sizeof(*mp));
569 if (unlikely(mp == NULL))
571 libvlc_printerr("Not enough memory");
572 return NULL;
575 /* Input */
576 var_Create (mp, "rate", VLC_VAR_FLOAT|VLC_VAR_DOINHERIT);
577 var_Create (mp, "sout", VLC_VAR_STRING);
578 var_Create (mp, "demux-filter", VLC_VAR_STRING);
580 /* Video */
581 var_Create (mp, "vout", VLC_VAR_STRING|VLC_VAR_DOINHERIT);
582 var_Create (mp, "window", VLC_VAR_STRING);
583 var_Create (mp, "gl", VLC_VAR_STRING);
584 var_Create (mp, "gles2", VLC_VAR_STRING);
585 var_Create (mp, "vmem-lock", VLC_VAR_ADDRESS);
586 var_Create (mp, "vmem-unlock", VLC_VAR_ADDRESS);
587 var_Create (mp, "vmem-display", VLC_VAR_ADDRESS);
588 var_Create (mp, "vmem-data", VLC_VAR_ADDRESS);
589 var_Create (mp, "vmem-setup", VLC_VAR_ADDRESS);
590 var_Create (mp, "vmem-cleanup", VLC_VAR_ADDRESS);
591 var_Create (mp, "vmem-chroma", VLC_VAR_STRING | VLC_VAR_DOINHERIT);
592 var_Create (mp, "vmem-width", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
593 var_Create (mp, "vmem-height", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
594 var_Create (mp, "vmem-pitch", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
596 var_Create( mp, "vout-cb-opaque", VLC_VAR_ADDRESS );
597 var_Create( mp, "vout-cb-setup", VLC_VAR_ADDRESS );
598 var_Create( mp, "vout-cb-cleanup", VLC_VAR_ADDRESS );
599 var_Create( mp, "vout-cb-resize-cb", VLC_VAR_ADDRESS );
600 var_Create( mp, "vout-cb-update-output", VLC_VAR_ADDRESS );
601 var_Create( mp, "vout-cb-swap", VLC_VAR_ADDRESS );
602 var_Create( mp, "vout-cb-get-proc-address", VLC_VAR_ADDRESS );
603 var_Create( mp, "vout-cb-make-current", VLC_VAR_ADDRESS );
604 var_Create( mp, "vout-cb-metadata", VLC_VAR_ADDRESS );
605 var_Create( mp, "vout-cb-select-plane", VLC_VAR_ADDRESS );
607 var_Create (mp, "dec-dev", VLC_VAR_STRING);
608 var_Create (mp, "drawable-xid", VLC_VAR_INTEGER);
609 #if defined (_WIN32) || defined (__OS2__)
610 var_Create (mp, "drawable-hwnd", VLC_VAR_INTEGER);
611 #endif
612 #ifdef __APPLE__
613 var_Create (mp, "drawable-nsobject", VLC_VAR_ADDRESS);
614 #endif
615 #ifdef __ANDROID__
616 var_Create (mp, "drawable-androidwindow", VLC_VAR_ADDRESS);
617 #endif
619 var_Create (mp, "keyboard-events", VLC_VAR_BOOL);
620 var_SetBool (mp, "keyboard-events", true);
621 var_Create (mp, "mouse-events", VLC_VAR_BOOL);
622 var_SetBool (mp, "mouse-events", true);
624 var_Create (mp, "fullscreen", VLC_VAR_BOOL);
625 var_Create (mp, "autoscale", VLC_VAR_BOOL | VLC_VAR_DOINHERIT);
626 var_Create (mp, "zoom", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT);
627 var_Create (mp, "aspect-ratio", VLC_VAR_STRING);
628 var_Create (mp, "crop", VLC_VAR_STRING);
629 var_Create (mp, "deinterlace", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
630 var_Create (mp, "deinterlace-mode", VLC_VAR_STRING | VLC_VAR_DOINHERIT);
632 var_Create (mp, "vbi-page", VLC_VAR_INTEGER);
633 var_SetInteger (mp, "vbi-page", 100);
635 var_Create (mp, "video-filter", VLC_VAR_STRING | VLC_VAR_DOINHERIT);
636 var_Create (mp, "sub-source", VLC_VAR_STRING | VLC_VAR_DOINHERIT);
637 var_Create (mp, "sub-filter", VLC_VAR_STRING | VLC_VAR_DOINHERIT);
639 var_Create (mp, "marq-marquee", VLC_VAR_STRING);
640 var_Create (mp, "marq-color", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
641 var_Create (mp, "marq-opacity", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
642 var_Create (mp, "marq-position", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
643 var_Create (mp, "marq-refresh", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
644 var_Create (mp, "marq-size", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
645 var_Create (mp, "marq-timeout", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
646 var_Create (mp, "marq-x", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
647 var_Create (mp, "marq-y", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
649 var_Create (mp, "logo-file", VLC_VAR_STRING);
650 var_Create (mp, "logo-x", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
651 var_Create (mp, "logo-y", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
652 var_Create (mp, "logo-delay", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
653 var_Create (mp, "logo-repeat", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
654 var_Create (mp, "logo-opacity", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
655 var_Create (mp, "logo-position", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
657 var_Create (mp, "contrast", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT);
658 var_Create (mp, "brightness", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT);
659 var_Create (mp, "hue", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT);
660 var_Create (mp, "saturation", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT);
661 var_Create (mp, "gamma", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT);
663 /* Audio */
664 var_Create (mp, "aout", VLC_VAR_STRING | VLC_VAR_DOINHERIT);
665 var_Create (mp, "audio-device", VLC_VAR_STRING);
666 var_Create (mp, "mute", VLC_VAR_BOOL);
667 var_Create (mp, "volume", VLC_VAR_FLOAT);
668 var_Create (mp, "corks", VLC_VAR_INTEGER);
669 var_Create (mp, "audio-filter", VLC_VAR_STRING);
670 var_Create (mp, "role", VLC_VAR_STRING | VLC_VAR_DOINHERIT);
671 var_Create (mp, "amem-data", VLC_VAR_ADDRESS);
672 var_Create (mp, "amem-setup", VLC_VAR_ADDRESS);
673 var_Create (mp, "amem-cleanup", VLC_VAR_ADDRESS);
674 var_Create (mp, "amem-play", VLC_VAR_ADDRESS);
675 var_Create (mp, "amem-pause", VLC_VAR_ADDRESS);
676 var_Create (mp, "amem-resume", VLC_VAR_ADDRESS);
677 var_Create (mp, "amem-flush", VLC_VAR_ADDRESS);
678 var_Create (mp, "amem-drain", VLC_VAR_ADDRESS);
679 var_Create (mp, "amem-set-volume", VLC_VAR_ADDRESS);
680 var_Create (mp, "amem-format", VLC_VAR_STRING | VLC_VAR_DOINHERIT);
681 var_Create (mp, "amem-rate", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
682 var_Create (mp, "amem-channels", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
684 /* Video Title */
685 var_Create (mp, "video-title-show", VLC_VAR_BOOL);
686 var_Create (mp, "video-title-position", VLC_VAR_INTEGER);
687 var_Create (mp, "video-title-timeout", VLC_VAR_INTEGER);
689 /* Equalizer */
690 var_Create (mp, "equalizer-preamp", VLC_VAR_FLOAT);
691 var_Create (mp, "equalizer-vlcfreqs", VLC_VAR_BOOL);
692 var_Create (mp, "equalizer-bands", VLC_VAR_STRING);
694 /* Initialize the shared HTTP cookie jar */
695 vlc_value_t cookies;
696 cookies.p_address = vlc_http_cookies_new();
697 if ( likely(cookies.p_address) )
699 var_Create(mp, "http-cookies", VLC_VAR_ADDRESS);
700 var_SetChecked(mp, "http-cookies", VLC_VAR_ADDRESS, cookies);
703 mp->p_md = NULL;
704 mp->p_libvlc_instance = instance;
705 /* use a reentrant lock to allow calling libvlc functions from callbacks */
706 mp->player = vlc_player_New(VLC_OBJECT(mp), VLC_PLAYER_LOCK_REENTRANT,
707 NULL, NULL);
708 if (unlikely(!mp->player))
709 goto error1;
711 vlc_player_Lock(mp->player);
713 mp->listener = vlc_player_AddListener(mp->player, &vlc_player_cbs, mp);
714 if (unlikely(!mp->listener))
715 goto error2;
717 mp->aout_listener =
718 vlc_player_aout_AddListener(mp->player, &vlc_player_aout_cbs, mp);
719 if (unlikely(!mp->aout_listener))
720 goto error3;
722 vlc_player_Unlock(mp->player);
724 mp->i_refcount = 1;
725 libvlc_event_manager_init(&mp->event_manager, mp);
727 /* Snapshot initialization */
728 /* Attach a var callback to the global object to provide the glue between
729 * vout_thread that generates the event and media_player that re-emits it
730 * with its own event manager
732 * FIXME: It's unclear why we want to put this in public API, and why we
733 * want to expose it in such a limiting and ugly way.
735 var_AddCallback(vlc_object_instance(mp),
736 "snapshot-file", snapshot_was_taken, mp);
738 libvlc_retain(instance);
739 return mp;
741 error3:
742 vlc_player_RemoveListener(mp->player, mp->listener);
743 error2:
744 vlc_player_Unlock(mp->player);
745 vlc_player_Delete(mp->player);
746 error1:
747 vlc_object_delete(mp);
748 return NULL;
751 /**************************************************************************
752 * Create a Media Instance object with a media descriptor.
753 **************************************************************************/
754 libvlc_media_player_t *
755 libvlc_media_player_new_from_media( libvlc_media_t * p_md )
757 libvlc_media_player_t * p_mi;
759 p_mi = libvlc_media_player_new( p_md->p_libvlc_instance );
760 if( !p_mi )
761 return NULL;
763 libvlc_media_retain( p_md );
764 p_mi->p_md = p_md;
765 media_attach_preparsed_event(p_md);
767 vlc_player_Lock(p_mi->player);
768 int ret = vlc_player_SetCurrentMedia(p_mi->player, p_md->p_input_item);
769 vlc_player_Unlock(p_mi->player);
771 if (ret != VLC_SUCCESS)
773 media_detach_preparsed_event(p_md);
774 libvlc_media_release(p_md);
775 p_mi->p_md = NULL;
776 return NULL;
779 return p_mi;
782 /**************************************************************************
783 * Destroy a Media Instance object (libvlc internal)
785 * Warning: No lock held here, but hey, this is internal. Caller must lock.
786 **************************************************************************/
787 static void libvlc_media_player_destroy( libvlc_media_player_t *p_mi )
789 assert( p_mi );
791 /* Detach Callback from the main libvlc object */
792 var_DelCallback( vlc_object_instance(p_mi),
793 "snapshot-file", snapshot_was_taken, p_mi );
795 vlc_player_Lock(p_mi->player);
796 vlc_player_aout_RemoveListener(p_mi->player, p_mi->aout_listener);
797 vlc_player_RemoveListener(p_mi->player, p_mi->listener);
798 vlc_player_Unlock(p_mi->player);
800 vlc_player_Delete(p_mi->player);
802 if (p_mi->p_md)
803 media_detach_preparsed_event(p_mi->p_md);
804 libvlc_event_manager_destroy(&p_mi->event_manager);
805 libvlc_media_release( p_mi->p_md );
807 vlc_http_cookie_jar_t *cookies = var_GetAddress( p_mi, "http-cookies" );
808 if ( cookies )
810 var_Destroy( p_mi, "http-cookies" );
811 vlc_http_cookies_destroy( cookies );
814 libvlc_instance_t *instance = p_mi->p_libvlc_instance;
815 vlc_object_delete(p_mi);
816 libvlc_release(instance);
819 /**************************************************************************
820 * Release a Media Instance object.
822 * Function does the locking.
823 **************************************************************************/
824 void libvlc_media_player_release( libvlc_media_player_t *p_mi )
826 bool destroy;
828 assert( p_mi );
829 vlc_player_Lock(p_mi->player);
830 destroy = !--p_mi->i_refcount;
831 vlc_player_Unlock(p_mi->player);
833 if( destroy )
834 libvlc_media_player_destroy( p_mi );
837 /**************************************************************************
838 * Retain a Media Instance object.
840 * Caller must hold the lock.
841 **************************************************************************/
842 void libvlc_media_player_retain( libvlc_media_player_t *p_mi )
844 assert( p_mi );
846 vlc_player_Lock(p_mi->player);
847 p_mi->i_refcount++;
848 vlc_player_Unlock(p_mi->player);
851 /**************************************************************************
852 * Set the Media descriptor associated with the instance.
854 * Enter without lock -- function will lock the object.
855 **************************************************************************/
856 void libvlc_media_player_set_media(
857 libvlc_media_player_t *p_mi,
858 libvlc_media_t *p_md )
860 vlc_player_Lock(p_mi->player);
862 if (p_mi->p_md)
863 media_detach_preparsed_event(p_mi->p_md);
865 libvlc_media_release( p_mi->p_md );
867 if( p_md )
869 libvlc_media_retain( p_md );
870 media_attach_preparsed_event(p_md);
872 p_mi->p_md = p_md;
874 vlc_player_SetCurrentMedia(p_mi->player, p_md->p_input_item);
876 /* The policy here is to ignore that we were created using a different
877 * libvlc_instance, because we don't really care */
878 p_mi->p_libvlc_instance = p_md->p_libvlc_instance;
880 vlc_player_Unlock(p_mi->player);
883 /**************************************************************************
884 * Get the Media descriptor associated with the instance.
885 **************************************************************************/
886 libvlc_media_t *
887 libvlc_media_player_get_media( libvlc_media_player_t *p_mi )
889 libvlc_media_t *p_m;
891 vlc_player_Lock(p_mi->player);
892 p_m = p_mi->p_md;
893 if( p_m )
894 libvlc_media_retain( p_m );
895 vlc_player_Unlock(p_mi->player);
897 return p_m;
900 /**************************************************************************
901 * Get the event Manager.
902 **************************************************************************/
903 libvlc_event_manager_t *
904 libvlc_media_player_event_manager( libvlc_media_player_t *p_mi )
906 return &p_mi->event_manager;
909 /**************************************************************************
910 * Tell media player to start playing.
911 **************************************************************************/
912 int libvlc_media_player_play( libvlc_media_player_t *p_mi )
914 vlc_player_t *player = p_mi->player;
915 vlc_player_Lock(player);
917 int ret = vlc_player_Start(player);
918 if (ret == VLC_SUCCESS)
920 if (vlc_player_IsPaused(player))
921 vlc_player_Resume(player);
924 vlc_player_Unlock(player);
925 return ret;
928 void libvlc_media_player_set_pause( libvlc_media_player_t *p_mi, int paused )
930 vlc_player_t *player = p_mi->player;
931 vlc_player_Lock(player);
933 if (paused)
935 if (vlc_player_CanPause(player))
936 vlc_player_Pause(player);
937 else
938 vlc_player_Stop(player);
940 else
942 vlc_player_Resume(player);
945 vlc_player_Unlock(player);
948 /**************************************************************************
949 * Toggle pause.
950 **************************************************************************/
951 void libvlc_media_player_pause( libvlc_media_player_t *p_mi )
953 vlc_player_t *player = p_mi->player;
954 vlc_player_Lock(player);
956 vlc_player_TogglePause(player);
958 vlc_player_Unlock(player);
961 /**************************************************************************
962 * Tells whether the media player is currently playing.
963 **************************************************************************/
964 bool libvlc_media_player_is_playing(libvlc_media_player_t *p_mi)
966 vlc_player_t *player = p_mi->player;
967 vlc_player_Lock(player);
969 bool ret = vlc_player_IsStarted(player) && !vlc_player_IsPaused(player);
971 vlc_player_Unlock(player);
972 return ret;
975 /**************************************************************************
976 * Stop playing.
977 **************************************************************************/
978 int libvlc_media_player_stop_async( libvlc_media_player_t *p_mi )
980 vlc_player_t *player = p_mi->player;
981 vlc_player_Lock(player);
983 int ret = vlc_player_Stop(player);
985 vlc_player_Unlock(player);
987 return ret;
990 int libvlc_media_player_set_renderer( libvlc_media_player_t *p_mi,
991 libvlc_renderer_item_t *p_litem )
993 vlc_player_t *player = p_mi->player;
994 vlc_player_Lock(player);
996 vlc_renderer_item_t *renderer = libvlc_renderer_item_to_vlc(p_litem);
997 vlc_player_SetRenderer(player, renderer);
999 vlc_player_Unlock(player);
1000 return 0;
1003 void libvlc_video_set_callbacks( libvlc_media_player_t *mp,
1004 void *(*lock_cb) (void *, void **),
1005 void (*unlock_cb) (void *, void *, void *const *),
1006 void (*display_cb) (void *, void *),
1007 void *opaque )
1009 var_SetAddress( mp, "vmem-lock", lock_cb );
1010 var_SetAddress( mp, "vmem-unlock", unlock_cb );
1011 var_SetAddress( mp, "vmem-display", display_cb );
1012 var_SetAddress( mp, "vmem-data", opaque );
1013 var_SetString( mp, "dec-dev", "none" );
1014 var_SetString( mp, "vout", "vmem" );
1015 var_SetString( mp, "window", "dummy" );
1018 void libvlc_video_set_format_callbacks( libvlc_media_player_t *mp,
1019 libvlc_video_format_cb setup,
1020 libvlc_video_cleanup_cb cleanup )
1022 var_SetAddress( mp, "vmem-setup", setup );
1023 var_SetAddress( mp, "vmem-cleanup", cleanup );
1026 void libvlc_video_set_format( libvlc_media_player_t *mp, const char *chroma,
1027 unsigned width, unsigned height, unsigned pitch )
1029 var_SetString( mp, "vmem-chroma", chroma );
1030 var_SetInteger( mp, "vmem-width", width );
1031 var_SetInteger( mp, "vmem-height", height );
1032 var_SetInteger( mp, "vmem-pitch", pitch );
1035 bool libvlc_video_set_output_callbacks(libvlc_media_player_t *mp,
1036 libvlc_video_engine_t engine,
1037 libvlc_video_output_setup_cb setup_cb,
1038 libvlc_video_output_cleanup_cb cleanup_cb,
1039 libvlc_video_output_set_resize_cb resize_cb,
1040 libvlc_video_update_output_cb update_output_cb,
1041 libvlc_video_swap_cb swap_cb,
1042 libvlc_video_makeCurrent_cb makeCurrent_cb,
1043 libvlc_video_getProcAddress_cb getProcAddress_cb,
1044 libvlc_video_frameMetadata_cb metadata_cb,
1045 libvlc_video_output_select_plane_cb select_plane_cb,
1046 void *opaque)
1048 #ifdef __ANDROID__
1049 //use the default android window
1050 var_SetString( mp, "window", "");
1051 #else
1052 var_SetString( mp, "window", "wextern");
1053 #endif
1055 if( engine == libvlc_video_engine_gles2 )
1057 var_SetString ( mp, "vout", "gles2" );
1058 var_SetString ( mp, "gles2", "vgl" );
1060 else if( engine == libvlc_video_engine_opengl )
1062 var_SetString ( mp, "vout", "gl" );
1063 var_SetString ( mp, "gl", "vgl");
1065 else if ( engine == libvlc_video_engine_d3d11 )
1067 var_SetString ( mp, "vout", "direct3d11" );
1068 var_SetString ( mp, "dec-dev", "d3d11" );
1070 else if ( engine == libvlc_video_engine_d3d9 )
1072 var_SetString ( mp, "vout", "direct3d9" );
1073 var_SetString ( mp, "dec-dev", "d3d9" );
1075 else
1076 return false;
1078 var_SetAddress( mp, "vout-cb-opaque", opaque );
1079 var_SetAddress( mp, "vout-cb-setup", setup_cb );
1080 var_SetAddress( mp, "vout-cb-cleanup", cleanup_cb );
1081 var_SetAddress( mp, "vout-cb-resize-cb", resize_cb );
1082 var_SetAddress( mp, "vout-cb-update-output", update_output_cb );
1083 var_SetAddress( mp, "vout-cb-swap", swap_cb );
1084 var_SetAddress( mp, "vout-cb-get-proc-address", getProcAddress_cb );
1085 var_SetAddress( mp, "vout-cb-make-current", makeCurrent_cb );
1086 var_SetAddress( mp, "vout-cb-metadata", metadata_cb );
1087 var_SetAddress( mp, "vout-cb-select-plane", select_plane_cb );
1088 return true;
1091 /**************************************************************************
1092 * set_nsobject
1093 **************************************************************************/
1094 void libvlc_media_player_set_nsobject( libvlc_media_player_t *p_mi,
1095 void * drawable )
1097 assert (p_mi != NULL);
1098 #ifdef __APPLE__
1099 var_SetString (p_mi, "dec-dev", "");
1100 var_SetString (p_mi, "vout", "");
1101 var_SetString (p_mi, "window", "");
1102 var_SetAddress (p_mi, "drawable-nsobject", drawable);
1103 #else
1104 (void)drawable;
1105 libvlc_printerr ("can't set nsobject: APPLE build required");
1106 assert(false);
1107 var_SetString (p_mi, "vout", "none");
1108 var_SetString (p_mi, "window", "none");
1109 #endif
1112 /**************************************************************************
1113 * get_nsobject
1114 **************************************************************************/
1115 void * libvlc_media_player_get_nsobject( libvlc_media_player_t *p_mi )
1117 assert (p_mi != NULL);
1118 #ifdef __APPLE__
1119 return var_GetAddress (p_mi, "drawable-nsobject");
1120 #else
1121 (void) p_mi;
1122 return NULL;
1123 #endif
1126 /**************************************************************************
1127 * set_xwindow
1128 **************************************************************************/
1129 void libvlc_media_player_set_xwindow( libvlc_media_player_t *p_mi,
1130 uint32_t drawable )
1132 assert (p_mi != NULL);
1134 var_SetString (p_mi, "dec-dev", "");
1135 var_SetString (p_mi, "vout", "");
1136 var_SetString (p_mi, "window", drawable ? "embed-xid,any" : "");
1137 var_SetInteger (p_mi, "drawable-xid", drawable);
1140 /**************************************************************************
1141 * get_xwindow
1142 **************************************************************************/
1143 uint32_t libvlc_media_player_get_xwindow( libvlc_media_player_t *p_mi )
1145 return var_GetInteger (p_mi, "drawable-xid");
1148 /**************************************************************************
1149 * set_hwnd
1150 **************************************************************************/
1151 void libvlc_media_player_set_hwnd( libvlc_media_player_t *p_mi,
1152 void *drawable )
1154 assert (p_mi != NULL);
1155 #if defined (_WIN32) || defined (__OS2__)
1156 var_SetString (p_mi, "dec-dev", "");
1157 var_SetString (p_mi, "vout", "");
1158 var_SetString (p_mi, "window",
1159 (drawable != NULL) ? "embed-hwnd,any" : "");
1160 var_SetInteger (p_mi, "drawable-hwnd", (uintptr_t)drawable);
1161 #else
1162 (void) drawable;
1163 libvlc_printerr ("can't set hwnd: WIN32 build required");
1164 assert(false);
1165 var_SetString (p_mi, "vout", "none");
1166 var_SetString (p_mi, "window", "none");
1167 #endif
1170 /**************************************************************************
1171 * get_hwnd
1172 **************************************************************************/
1173 void *libvlc_media_player_get_hwnd( libvlc_media_player_t *p_mi )
1175 assert (p_mi != NULL);
1176 #if defined (_WIN32) || defined (__OS2__)
1177 return (void *)(uintptr_t)var_GetInteger (p_mi, "drawable-hwnd");
1178 #else
1179 (void) p_mi;
1180 return NULL;
1181 #endif
1184 /**************************************************************************
1185 * set_android_context
1186 **************************************************************************/
1187 void libvlc_media_player_set_android_context( libvlc_media_player_t *p_mi,
1188 void *p_awindow_handler )
1190 assert (p_mi != NULL);
1191 #ifdef __ANDROID__
1192 var_SetAddress (p_mi, "drawable-androidwindow", p_awindow_handler);
1193 #else
1194 (void) p_awindow_handler;
1195 libvlc_printerr ("can't set android context: ANDROID build required");
1196 assert(false);
1197 var_SetString (p_mi, "vout", "none");
1198 var_SetString (p_mi, "window", "none");
1199 #endif
1202 void libvlc_audio_set_callbacks( libvlc_media_player_t *mp,
1203 libvlc_audio_play_cb play_cb,
1204 libvlc_audio_pause_cb pause_cb,
1205 libvlc_audio_resume_cb resume_cb,
1206 libvlc_audio_flush_cb flush_cb,
1207 libvlc_audio_drain_cb drain_cb,
1208 void *opaque )
1210 var_SetAddress( mp, "amem-play", play_cb );
1211 var_SetAddress( mp, "amem-pause", pause_cb );
1212 var_SetAddress( mp, "amem-resume", resume_cb );
1213 var_SetAddress( mp, "amem-flush", flush_cb );
1214 var_SetAddress( mp, "amem-drain", drain_cb );
1215 var_SetAddress( mp, "amem-data", opaque );
1216 var_SetString( mp, "aout", "amem,none" );
1219 void libvlc_audio_set_volume_callback( libvlc_media_player_t *mp,
1220 libvlc_audio_set_volume_cb cb )
1222 var_SetAddress( mp, "amem-set-volume", cb );
1225 void libvlc_audio_set_format_callbacks( libvlc_media_player_t *mp,
1226 libvlc_audio_setup_cb setup,
1227 libvlc_audio_cleanup_cb cleanup )
1229 var_SetAddress( mp, "amem-setup", setup );
1230 var_SetAddress( mp, "amem-cleanup", cleanup );
1233 void libvlc_audio_set_format( libvlc_media_player_t *mp, const char *format,
1234 unsigned rate, unsigned channels )
1236 var_SetString( mp, "amem-format", format );
1237 var_SetInteger( mp, "amem-rate", rate );
1238 var_SetInteger( mp, "amem-channels", channels );
1242 /**************************************************************************
1243 * Getters for stream information
1244 **************************************************************************/
1245 libvlc_time_t libvlc_media_player_get_length(
1246 libvlc_media_player_t *p_mi )
1248 vlc_player_t *player = p_mi->player;
1249 vlc_player_Lock(player);
1251 vlc_tick_t length = vlc_player_GetLength(player);
1252 libvlc_time_t i_time = from_mtime(length);
1254 vlc_player_Unlock(player);
1255 return i_time;
1258 libvlc_time_t libvlc_media_player_get_time( libvlc_media_player_t *p_mi )
1260 vlc_player_t *player = p_mi->player;
1261 vlc_player_Lock(player);
1263 vlc_tick_t tick = vlc_player_GetTime(player);
1264 libvlc_time_t i_time = from_mtime(tick);
1266 vlc_player_Unlock(player);
1267 return i_time;
1270 int libvlc_media_player_set_time( libvlc_media_player_t *p_mi,
1271 libvlc_time_t i_time, bool b_fast )
1273 vlc_tick_t tick = to_mtime(i_time);
1275 vlc_player_t *player = p_mi->player;
1276 vlc_player_Lock(player);
1278 enum vlc_player_seek_speed speed = b_fast ? VLC_PLAYER_SEEK_FAST
1279 : VLC_PLAYER_SEEK_PRECISE;
1280 vlc_player_SeekByTime(player, tick, speed, VLC_PLAYER_WHENCE_ABSOLUTE);
1282 vlc_player_Unlock(player);
1284 /* may not fail anymore, keep int not to break the API */
1285 return 0;
1288 int libvlc_media_player_set_position( libvlc_media_player_t *p_mi,
1289 float position, bool b_fast )
1291 vlc_player_t *player = p_mi->player;
1292 vlc_player_Lock(player);
1294 enum vlc_player_seek_speed speed = b_fast ? VLC_PLAYER_SEEK_FAST
1295 : VLC_PLAYER_SEEK_PRECISE;
1296 vlc_player_SeekByPos(player, position, speed, VLC_PLAYER_WHENCE_ABSOLUTE);
1298 vlc_player_Unlock(player);
1300 /* may not fail anymore, keep int not to break the API */
1301 return 0;
1304 float libvlc_media_player_get_position( libvlc_media_player_t *p_mi )
1306 vlc_player_t *player = p_mi->player;
1307 vlc_player_Lock(player);
1309 float f_position = vlc_player_GetPosition(player);
1311 vlc_player_Unlock(player);
1312 return f_position;
1315 void libvlc_media_player_set_chapter( libvlc_media_player_t *p_mi,
1316 int chapter )
1318 vlc_player_t *player = p_mi->player;
1319 vlc_player_Lock(player);
1321 vlc_player_SelectChapterIdx(player, chapter);
1323 vlc_player_Unlock(player);
1326 int libvlc_media_player_get_chapter( libvlc_media_player_t *p_mi )
1328 vlc_player_t *player = p_mi->player;
1329 vlc_player_Lock(player);
1331 ssize_t i_chapter = vlc_player_GetSelectedChapterIdx(player);
1333 vlc_player_Unlock(player);
1334 return i_chapter;
1337 int libvlc_media_player_get_chapter_count( libvlc_media_player_t *p_mi )
1339 vlc_player_t *player = p_mi->player;
1340 vlc_player_Lock(player);
1342 const struct vlc_player_title *title = vlc_player_GetSelectedTitle(player);
1343 int ret = title ? (int) title->chapter_count : -1;
1345 vlc_player_Unlock(player);
1346 return ret;
1349 int libvlc_media_player_get_chapter_count_for_title(
1350 libvlc_media_player_t *p_mi,
1351 int i_title )
1353 assert(i_title >= 0);
1354 size_t idx = i_title;
1355 int ret = -1;
1357 vlc_player_t *player = p_mi->player;
1358 vlc_player_Lock(player);
1360 vlc_player_title_list *titles = vlc_player_GetTitleList(player);
1361 if (!titles)
1362 goto end;
1364 size_t titles_count = vlc_player_title_list_GetCount(titles);
1365 if (idx < titles_count)
1366 goto end;
1368 const struct vlc_player_title *title =
1369 vlc_player_title_list_GetAt(titles, idx);
1370 assert(title);
1372 ret = title->chapter_count;
1374 end:
1375 vlc_player_Unlock(player);
1376 return ret;
1379 void libvlc_media_player_set_title( libvlc_media_player_t *p_mi,
1380 int i_title )
1382 vlc_player_t *player = p_mi->player;
1383 vlc_player_Lock(player);
1385 vlc_player_SelectTitleIdx(player, i_title);
1387 vlc_player_Unlock(player);
1390 int libvlc_media_player_get_title( libvlc_media_player_t *p_mi )
1392 vlc_player_t *player = p_mi->player;
1393 vlc_player_Lock(player);
1395 ssize_t i_title = vlc_player_GetSelectedTitleIdx(player);
1397 vlc_player_Unlock(player);
1398 return i_title;
1401 int libvlc_media_player_get_title_count( libvlc_media_player_t *p_mi )
1403 vlc_player_t *player = p_mi->player;
1404 vlc_player_Lock(player);
1406 vlc_player_title_list *titles = vlc_player_GetTitleList(player);
1407 int ret = titles ? (int) vlc_player_title_list_GetCount(titles) : -1;
1409 vlc_player_Unlock(player);
1410 return ret;
1413 int libvlc_media_player_get_full_title_descriptions( libvlc_media_player_t *p_mi,
1414 libvlc_title_description_t *** pp_titles )
1416 assert( p_mi );
1418 int ret = -1;
1420 vlc_player_t *player = p_mi->player;
1421 vlc_player_Lock(player);
1423 vlc_player_title_list *titles = vlc_player_GetTitleList(player);
1424 if (!titles)
1425 goto end;
1427 size_t count = vlc_player_title_list_GetCount(titles);
1429 libvlc_title_description_t **descs = vlc_alloc(count, sizeof(*descs));
1430 if (count > 0 && !descs)
1431 goto end;
1433 for (size_t i = 0; i < count; i++)
1435 const struct vlc_player_title *title =
1436 vlc_player_title_list_GetAt(titles, i);
1437 libvlc_title_description_t *desc = malloc(sizeof(*desc));
1438 if (!desc)
1440 libvlc_title_descriptions_release(descs, i);
1441 goto end;
1444 descs[i] = desc;
1446 /* we want to return milliseconds to match the rest of the API */
1447 desc->i_duration = MS_FROM_VLC_TICK(title->length);
1448 desc->i_flags = title->flags;
1449 desc->psz_name = title->name ? strdup(title->name) : NULL;
1452 ret = count;
1453 *pp_titles = descs;
1455 end:
1456 vlc_player_Unlock(player);
1457 return ret;
1460 void libvlc_title_descriptions_release( libvlc_title_description_t **p_titles,
1461 unsigned i_count )
1463 for (unsigned i = 0; i < i_count; i++ )
1465 if ( !p_titles[i] )
1466 continue;
1468 free( p_titles[i]->psz_name );
1469 free( p_titles[i] );
1471 free( p_titles );
1474 int libvlc_media_player_get_full_chapter_descriptions( libvlc_media_player_t *p_mi,
1475 int i_chapters_of_title,
1476 libvlc_chapter_description_t *** pp_chapters )
1478 assert( p_mi );
1480 int ret = -1;
1482 vlc_player_t *player = p_mi->player;
1483 vlc_player_Lock(player);
1485 vlc_player_title_list *titles = vlc_player_GetTitleList(player);
1486 if (!titles)
1487 goto end;
1489 size_t titles_count = vlc_player_title_list_GetCount(titles);
1490 if (i_chapters_of_title < (int) titles_count)
1491 goto end;
1493 const struct vlc_player_title *title =
1494 vlc_player_title_list_GetAt(titles, i_chapters_of_title);
1495 assert(title);
1497 size_t i_chapter_count = title->chapter_count;
1499 libvlc_chapter_description_t **descs =
1500 vlc_alloc(i_chapter_count, sizeof(*descs));
1501 if (i_chapter_count > 0 && !descs)
1502 goto end;
1504 for (size_t i = 0; i < i_chapter_count; i++)
1506 const struct vlc_player_chapter *chapter = &title->chapters[i];
1507 libvlc_chapter_description_t *desc = malloc(sizeof(*desc));
1508 if (!desc)
1510 libvlc_chapter_descriptions_release(descs, i);
1511 goto end;
1514 descs[i] = desc;
1516 vlc_tick_t chapter_end = i < i_chapter_count - 1
1517 ? title->chapters[i + 1].time
1518 : title->length;
1519 desc->i_time_offset = MS_FROM_VLC_TICK(chapter->time);
1520 desc->psz_name = chapter->name ? strdup(chapter->name) : NULL;
1521 desc->i_duration = MS_FROM_VLC_TICK(chapter_end) - desc->i_time_offset;
1524 ret = i_chapter_count;
1525 *pp_chapters = descs;
1527 end:
1528 vlc_player_Unlock(player);
1529 return ret;
1532 void libvlc_chapter_descriptions_release( libvlc_chapter_description_t **p_chapters,
1533 unsigned i_count )
1535 for (unsigned i = 0; i < i_count; i++ )
1537 if ( !p_chapters[i] )
1538 continue;
1540 free( p_chapters[i]->psz_name );
1541 free( p_chapters[i] );
1543 free( p_chapters );
1546 void libvlc_media_player_next_chapter( libvlc_media_player_t *p_mi )
1548 vlc_player_t *player = p_mi->player;
1549 vlc_player_Lock(player);
1551 vlc_player_SelectNextChapter(player);
1553 vlc_player_Unlock(player);
1556 void libvlc_media_player_previous_chapter( libvlc_media_player_t *p_mi )
1558 vlc_player_t *player = p_mi->player;
1559 vlc_player_Lock(player);
1561 vlc_player_SelectPrevChapter(player);
1563 vlc_player_Unlock(player);
1566 int libvlc_media_player_set_rate( libvlc_media_player_t *p_mi, float rate )
1568 vlc_player_t *player = p_mi->player;
1569 vlc_player_Lock(player);
1571 vlc_player_ChangeRate(player, rate);
1573 vlc_player_Unlock(player);
1574 return 0;
1577 float libvlc_media_player_get_rate( libvlc_media_player_t *p_mi )
1579 vlc_player_t *player = p_mi->player;
1580 vlc_player_Lock(player);
1582 float rate = vlc_player_GetRate(player);
1584 vlc_player_Unlock(player);
1585 return rate;
1588 libvlc_state_t libvlc_media_player_get_state( libvlc_media_player_t *p_mi )
1590 vlc_player_t *player = p_mi->player;
1591 vlc_player_Lock(player);
1593 enum vlc_player_error error = vlc_player_GetError(player);
1594 enum vlc_player_state state = vlc_player_GetState(player);
1596 vlc_player_Unlock(player);
1598 if (error != VLC_PLAYER_ERROR_NONE)
1599 return libvlc_Error;
1600 switch (state) {
1601 case VLC_PLAYER_STATE_STOPPED:
1602 return libvlc_Stopped;
1603 case VLC_PLAYER_STATE_STOPPING:
1604 return libvlc_Ended;
1605 case VLC_PLAYER_STATE_STARTED:
1606 return libvlc_Opening;
1607 case VLC_PLAYER_STATE_PLAYING:
1608 return libvlc_Playing;
1609 case VLC_PLAYER_STATE_PAUSED:
1610 return libvlc_Paused;
1611 default:
1612 vlc_assert_unreachable();
1616 bool libvlc_media_player_is_seekable(libvlc_media_player_t *p_mi)
1618 vlc_player_t *player = p_mi->player;
1619 vlc_player_Lock(player);
1621 bool b_seekable = vlc_player_CanSeek(player);
1623 vlc_player_Unlock(player);
1624 return b_seekable;
1627 void libvlc_media_player_navigate( libvlc_media_player_t* p_mi,
1628 unsigned navigate )
1630 static const enum vlc_player_nav map[] =
1632 VLC_PLAYER_NAV_ACTIVATE, VLC_PLAYER_NAV_UP, VLC_PLAYER_NAV_DOWN,
1633 VLC_PLAYER_NAV_LEFT, VLC_PLAYER_NAV_RIGHT, VLC_PLAYER_NAV_POPUP,
1636 if( navigate >= sizeof(map) / sizeof(map[0]) )
1637 return;
1639 vlc_player_t *player = p_mi->player;
1640 vlc_player_Lock(player);
1642 vlc_player_Navigate(player, map[navigate]);
1644 vlc_player_Unlock(player);
1647 /* internal function, used by audio, video */
1648 libvlc_track_description_t *
1649 libvlc_get_track_description( libvlc_media_player_t *p_mi,
1650 enum es_format_category_e cat )
1652 vlc_player_t *player = p_mi->player;
1653 vlc_player_Lock(player);
1655 libvlc_track_description_t *ret, **pp = &ret;
1657 size_t count = vlc_player_GetTrackCount(player, cat);
1658 for (size_t i = 0; i < count; i++)
1660 libvlc_track_description_t *tr = malloc(sizeof (*tr));
1661 if (unlikely(tr == NULL))
1663 libvlc_printerr("Not enough memory");
1664 continue;
1667 const struct vlc_player_track *track =
1668 vlc_player_GetTrackAt(player, cat, i);
1670 *pp = tr;
1671 tr->i_id = vlc_es_id_GetInputId(track->es_id);
1672 tr->psz_name = strdup(track->name);
1673 if (unlikely(!tr->psz_name))
1675 free(tr);
1676 continue;
1678 pp = &tr->p_next;
1681 *pp = NULL;
1683 vlc_player_Unlock(player);
1684 return ret;
1687 void libvlc_track_description_list_release( libvlc_track_description_t *p_td )
1689 libvlc_track_description_t *p_actual, *p_before;
1690 p_actual = p_td;
1692 while ( p_actual )
1694 free( p_actual->psz_name );
1695 p_before = p_actual;
1696 p_actual = p_before->p_next;
1697 free( p_before );
1701 bool libvlc_media_player_can_pause(libvlc_media_player_t *p_mi)
1703 vlc_player_t *player = p_mi->player;
1704 vlc_player_Lock(player);
1706 bool b_can_pause = vlc_player_CanPause(player);
1708 vlc_player_Unlock(player);
1709 return b_can_pause;
1712 bool libvlc_media_player_program_scrambled(libvlc_media_player_t *p_mi)
1714 bool b_program_scrambled = false;
1716 vlc_player_t *player = p_mi->player;
1717 vlc_player_Lock(player);
1719 const struct vlc_player_program *program =
1720 vlc_player_GetSelectedProgram(player);
1721 if (!program)
1722 goto end;
1724 b_program_scrambled = program->scrambled;
1726 vlc_player_Unlock(player);
1727 end:
1728 return b_program_scrambled;
1731 void libvlc_media_player_next_frame( libvlc_media_player_t *p_mi )
1733 vlc_player_t *player = p_mi->player;
1734 vlc_player_Lock(player);
1736 vlc_player_NextVideoFrame(player);
1738 vlc_player_Unlock(player);
1742 * Private lookup table to get subpicture alignment flag values corresponding
1743 * to a libvlc_position_t enumerated value.
1745 static const unsigned char position_subpicture_alignment[] = {
1746 [libvlc_position_center] = 0,
1747 [libvlc_position_left] = SUBPICTURE_ALIGN_LEFT,
1748 [libvlc_position_right] = SUBPICTURE_ALIGN_RIGHT,
1749 [libvlc_position_top] = SUBPICTURE_ALIGN_TOP,
1750 [libvlc_position_top_left] = SUBPICTURE_ALIGN_TOP | SUBPICTURE_ALIGN_LEFT,
1751 [libvlc_position_top_right] = SUBPICTURE_ALIGN_TOP | SUBPICTURE_ALIGN_RIGHT,
1752 [libvlc_position_bottom] = SUBPICTURE_ALIGN_BOTTOM,
1753 [libvlc_position_bottom_left] = SUBPICTURE_ALIGN_BOTTOM | SUBPICTURE_ALIGN_LEFT,
1754 [libvlc_position_bottom_right] = SUBPICTURE_ALIGN_BOTTOM | SUBPICTURE_ALIGN_RIGHT
1757 void libvlc_media_player_set_video_title_display( libvlc_media_player_t *p_mi, libvlc_position_t position, unsigned timeout )
1759 assert( position >= libvlc_position_disable && position <= libvlc_position_bottom_right );
1761 if ( position != libvlc_position_disable )
1763 var_SetBool( p_mi, "video-title-show", true );
1764 var_SetInteger( p_mi, "video-title-position", position_subpicture_alignment[position] );
1765 var_SetInteger( p_mi, "video-title-timeout", timeout );
1767 else
1769 var_SetBool( p_mi, "video-title-show", false );
1773 int libvlc_media_player_add_slave( libvlc_media_player_t *p_mi,
1774 libvlc_media_slave_type_t i_type,
1775 const char *psz_uri, bool b_select )
1777 vlc_player_t *player = p_mi->player;
1778 vlc_player_Lock(player);
1780 enum es_format_category_e cat = i_type == libvlc_media_slave_type_subtitle
1781 ? SPU_ES
1782 : AUDIO_ES;
1784 int ret = vlc_player_AddAssociatedMedia(player, cat, psz_uri, b_select,
1785 false, false);
1787 vlc_player_Unlock(player);
1788 return ret;
1792 * Maximum size of a formatted equalizer amplification band frequency value.
1794 * The allowed value range is supposed to be constrained from -20.0 to 20.0.
1796 * The format string " %.07f" with a minimum value of "-20" gives a maximum
1797 * string length of e.g. " -19.1234567", i.e. 12 bytes (not including the null
1798 * terminator).
1800 #define EQZ_BAND_VALUE_SIZE 12
1802 int libvlc_media_player_set_equalizer( libvlc_media_player_t *p_mi, libvlc_equalizer_t *p_equalizer )
1804 char bands[EQZ_BANDS_MAX * EQZ_BAND_VALUE_SIZE + 1];
1806 if( p_equalizer != NULL )
1808 for( unsigned i = 0, c = 0; i < EQZ_BANDS_MAX; i++ )
1810 c += snprintf( bands + c, sizeof(bands) - c, " %.07f",
1811 p_equalizer->f_amp[i] );
1812 if( unlikely(c >= sizeof(bands)) )
1813 return -1;
1816 var_SetFloat( p_mi, "equalizer-preamp", p_equalizer->f_preamp );
1817 var_SetString( p_mi, "equalizer-bands", bands );
1819 var_SetString( p_mi, "audio-filter", p_equalizer ? "equalizer" : "" );
1821 audio_output_t *p_aout = vlc_player_aout_Hold( p_mi->player );
1822 if( p_aout != NULL )
1824 if( p_equalizer != NULL )
1826 var_SetFloat( p_aout, "equalizer-preamp", p_equalizer->f_preamp );
1827 var_SetString( p_aout, "equalizer-bands", bands );
1830 var_SetString( p_aout, "audio-filter", p_equalizer ? "equalizer" : "" );
1831 aout_Release(p_aout);
1834 return 0;
1837 static const char roles[][16] =
1839 [libvlc_role_Music] = "music",
1840 [libvlc_role_Video] = "video",
1841 [libvlc_role_Communication] = "communication",
1842 [libvlc_role_Game] = "game",
1843 [libvlc_role_Notification] = "notification",
1844 [libvlc_role_Animation] = "animation",
1845 [libvlc_role_Production] = "production",
1846 [libvlc_role_Accessibility] = "accessibility",
1847 [libvlc_role_Test] = "test",
1850 int libvlc_media_player_set_role(libvlc_media_player_t *mp, unsigned role)
1852 if (role >= ARRAY_SIZE(roles)
1853 || var_SetString(mp, "role", roles[role]) != VLC_SUCCESS)
1854 return -1;
1855 return 0;
1858 int libvlc_media_player_get_role(libvlc_media_player_t *mp)
1860 int ret = -1;
1861 char *str = var_GetString(mp, "role");
1862 if (str == NULL)
1863 return 0;
1865 for (size_t i = 0; i < ARRAY_SIZE(roles); i++)
1866 if (!strcmp(roles[i], str))
1868 ret = i;
1869 break;
1872 free(str);
1873 return ret;
1876 #include <vlc_vout_display.h>
1878 /* make sure surface structures from libvlc can be passed as such to vlc
1879 otherwise we will need wrappers between what libvlc understands and what vlc uses */
1880 #define cast_ libvlc_video_color_space_t
1881 static_assert(libvlc_video_colorspace_BT601 == (cast_)COLOR_SPACE_BT601 &&
1882 libvlc_video_colorspace_BT709 == (cast_)COLOR_SPACE_BT709 &&
1883 libvlc_video_colorspace_BT2020 == (cast_)COLOR_SPACE_BT2020
1884 , "libvlc video colorspace mismatch");
1885 #undef cast_
1887 #define cast_ libvlc_video_transfer_func_t
1888 static_assert(libvlc_video_transfer_func_LINEAR == (cast_)TRANSFER_FUNC_LINEAR &&
1889 libvlc_video_transfer_func_SRGB == (cast_)TRANSFER_FUNC_SRGB &&
1890 libvlc_video_transfer_func_BT470_BG == (cast_)TRANSFER_FUNC_BT470_BG &&
1891 libvlc_video_transfer_func_BT470_M == (cast_)TRANSFER_FUNC_BT470_M &&
1892 libvlc_video_transfer_func_BT709 == (cast_)TRANSFER_FUNC_BT709 &&
1893 libvlc_video_transfer_func_PQ == (cast_)TRANSFER_FUNC_SMPTE_ST2084 &&
1894 libvlc_video_transfer_func_SMPTE_240 == (cast_)TRANSFER_FUNC_SMPTE_240 &&
1895 libvlc_video_transfer_func_HLG == (cast_)TRANSFER_FUNC_HLG
1896 , "libvlc video transfer function mismatch");
1897 #undef cast_
1899 #define cast_ libvlc_video_color_primaries_t
1900 static_assert(libvlc_video_primaries_BT601_525 == (cast_)COLOR_PRIMARIES_BT601_525 &&
1901 libvlc_video_primaries_BT601_625 == (cast_)COLOR_PRIMARIES_BT601_625 &&
1902 libvlc_video_primaries_BT709 == (cast_)COLOR_PRIMARIES_BT709 &&
1903 libvlc_video_primaries_BT2020 == (cast_)COLOR_PRIMARIES_BT2020 &&
1904 libvlc_video_primaries_DCI_P3 == (cast_)COLOR_PRIMARIES_DCI_P3 &&
1905 libvlc_video_primaries_BT470_M == (cast_)COLOR_PRIMARIES_BT470_M
1906 , "libvlc video color primaries mismatch");
1907 #undef cast_