📄 media_player.c
字号:
/***************************************************************************** * media_player.c: Libvlc API Media Instance management functions ***************************************************************************** * Copyright (C) 2005 the VideoLAN team * $Id$ * * Authors: Clément Stenac <zorglub@videolan.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/#include "libvlc_internal.h"#include <vlc/libvlc.h>#include <vlc_demux.h>#include <vlc_input.h>#include <vlc_vout.h>#include "libvlc.h"static voidinput_state_changed( const vlc_event_t * event, void * p_userdata );static intinput_seekable_changed( vlc_object_t * p_this, char const * psz_cmd, vlc_value_t oldval, vlc_value_t newval, void * p_userdata );static intinput_pausable_changed( vlc_object_t * p_this, char const * psz_cmd, vlc_value_t oldval, vlc_value_t newval, void * p_userdata );static intinput_position_changed( vlc_object_t * p_this, char const * psz_cmd, vlc_value_t oldval, vlc_value_t newval, void * p_userdata );static intinput_time_changed( vlc_object_t * p_this, char const * psz_cmd, vlc_value_t oldval, vlc_value_t newval, void * p_userdata );static const libvlc_state_t vlc_to_libvlc_state_array[] ={ [INIT_S] = libvlc_NothingSpecial, [OPENING_S] = libvlc_Opening, [BUFFERING_S] = libvlc_Buffering, [PLAYING_S] = libvlc_Playing, [PAUSE_S] = libvlc_Paused, [STOP_S] = libvlc_Stopped, [FORWARD_S] = libvlc_Forward, [BACKWARD_S] = libvlc_Backward, [END_S] = libvlc_Ended, [ERROR_S] = libvlc_Error,};static inline libvlc_state_t vlc_to_libvlc_state( int vlc_state ){ if( vlc_state < 0 || vlc_state > 6 ) return libvlc_Ended; return vlc_to_libvlc_state_array[vlc_state];}/* * Release the associated input thread * * Object lock is NOT held. */static void release_input_thread( libvlc_media_player_t *p_mi ){ input_thread_t * p_input_thread; if( !p_mi || !p_mi->p_input_thread ) return; p_input_thread = p_mi->p_input_thread; /* No one is tracking this input_thread appart us. Destroy it */ if( p_mi->b_own_its_input_thread ) { vlc_event_manager_t * p_em = input_get_event_manager( p_input_thread ); vlc_event_detach( p_em, vlc_InputStateChanged, input_state_changed, p_mi ); var_DelCallback( p_input_thread, "seekable", input_seekable_changed, p_mi ); var_DelCallback( p_input_thread, "pausable", input_pausable_changed, p_mi ); var_DelCallback( p_input_thread, "intf-change", input_position_changed, p_mi ); var_DelCallback( p_input_thread, "intf-change", input_time_changed, p_mi ); /* We owned this one */ input_StopThread( p_input_thread ); vlc_thread_join( p_input_thread ); var_Destroy( p_input_thread, "drawable" ); } vlc_object_release( p_input_thread ); p_mi->p_input_thread = NULL;}/* * Retrieve the input thread. Be sure to release the object * once you are done with it. (libvlc Internal) * * Object lock is held. */input_thread_t *libvlc_get_input_thread( libvlc_media_player_t *p_mi, libvlc_exception_t *p_e ){ input_thread_t *p_input_thread; if( !p_mi ) RAISENULL( "Media Instance is NULL" ); vlc_mutex_lock( &p_mi->object_lock ); if( !p_mi->p_input_thread ) { vlc_mutex_unlock( &p_mi->object_lock ); RAISENULL( "Input is NULL" ); } p_input_thread = p_mi->p_input_thread; vlc_object_yield( p_input_thread ); vlc_mutex_unlock( &p_mi->object_lock ); return p_input_thread;}/* * input_state_changed (Private) (vlc_InputStateChanged callback) */static voidinput_state_changed( const vlc_event_t * event, void * p_userdata ){ libvlc_media_player_t * p_mi = p_userdata; libvlc_event_t forwarded_event; libvlc_event_type_t type = event->u.input_state_changed.new_state; switch ( type ) { case INIT_S: libvlc_media_set_state( p_mi->p_md, libvlc_NothingSpecial, NULL); forwarded_event.type = libvlc_MediaPlayerNothingSpecial; break; case OPENING_S: libvlc_media_set_state( p_mi->p_md, libvlc_Opening, NULL); forwarded_event.type = libvlc_MediaPlayerOpening; break; case BUFFERING_S: libvlc_media_set_state( p_mi->p_md, libvlc_Buffering, NULL); forwarded_event.type = libvlc_MediaPlayerBuffering; break; case PLAYING_S: libvlc_media_set_state( p_mi->p_md, libvlc_Playing, NULL); forwarded_event.type = libvlc_MediaPlayerPlaying; break; case PAUSE_S: libvlc_media_set_state( p_mi->p_md, libvlc_Paused, NULL); forwarded_event.type = libvlc_MediaPlayerPaused; break; case STOP_S: libvlc_media_set_state( p_mi->p_md, libvlc_Stopped, NULL); forwarded_event.type = libvlc_MediaPlayerStopped; break; case FORWARD_S: libvlc_media_set_state( p_mi->p_md, libvlc_Forward, NULL); forwarded_event.type = libvlc_MediaPlayerForward; break; case BACKWARD_S: libvlc_media_set_state( p_mi->p_md, libvlc_Backward, NULL); forwarded_event.type = libvlc_MediaPlayerBackward; break; case END_S: libvlc_media_set_state( p_mi->p_md, libvlc_Ended, NULL); forwarded_event.type = libvlc_MediaPlayerEndReached; break; case ERROR_S: libvlc_media_set_state( p_mi->p_md, libvlc_Error, NULL); forwarded_event.type = libvlc_MediaPlayerEncounteredError; break; default: return; } libvlc_event_send( p_mi->p_event_manager, &forwarded_event ); return;}static intinput_seekable_changed( vlc_object_t * p_this, char const * psz_cmd, vlc_value_t oldval, vlc_value_t newval, void * p_userdata ){ VLC_UNUSED(oldval); VLC_UNUSED(p_this); VLC_UNUSED(psz_cmd); libvlc_media_player_t * p_mi = p_userdata; libvlc_event_t event; libvlc_media_set_state( p_mi->p_md, libvlc_NothingSpecial, NULL); event.type = libvlc_MediaPlayerSeekableChanged; event.u.media_player_seekable_changed.new_seekable = newval.b_bool; libvlc_event_send( p_mi->p_event_manager, &event ); return VLC_SUCCESS;}static intinput_pausable_changed( vlc_object_t * p_this, char const * psz_cmd, vlc_value_t oldval, vlc_value_t newval, void * p_userdata ){ VLC_UNUSED(oldval); VLC_UNUSED(p_this); VLC_UNUSED(psz_cmd); libvlc_media_player_t * p_mi = p_userdata; libvlc_event_t event; libvlc_media_set_state( p_mi->p_md, libvlc_NothingSpecial, NULL); event.type = libvlc_MediaPlayerPausableChanged; event.u.media_player_pausable_changed.new_pausable = newval.b_bool; libvlc_event_send( p_mi->p_event_manager, &event ); return VLC_SUCCESS;}/* * input_position_changed (Private) (input var "intf-change" Callback) */static intinput_position_changed( vlc_object_t * p_this, char const * psz_cmd, vlc_value_t oldval, vlc_value_t newval, void * p_userdata ){ VLC_UNUSED(oldval); libvlc_media_player_t * p_mi = p_userdata; vlc_value_t val; if (!strncmp(psz_cmd, "intf", 4 /* "-change" no need to go further */)) { input_thread_t * p_input = (input_thread_t *)p_this; var_Get( p_input, "state", &val ); if( val.i_int != PLAYING_S ) return VLC_SUCCESS; /* Don't send the position while stopped */ var_Get( p_input, "position", &val ); } else val.i_time = newval.i_time; libvlc_event_t event; event.type = libvlc_MediaPlayerPositionChanged; event.u.media_player_position_changed.new_position = val.f_float; libvlc_event_send( p_mi->p_event_manager, &event ); return VLC_SUCCESS;}/* * input_time_changed (Private) (input var "intf-change" Callback) */static intinput_time_changed( vlc_object_t * p_this, char const * psz_cmd, vlc_value_t oldval, vlc_value_t newval, void * p_userdata ){ VLC_UNUSED(oldval); libvlc_media_player_t * p_mi = p_userdata; vlc_value_t val; if (!strncmp(psz_cmd, "intf", 4 /* "-change" no need to go further */)) { input_thread_t * p_input = (input_thread_t *)p_this; var_Get( p_input, "state", &val ); if( val.i_int != PLAYING_S ) return VLC_SUCCESS; /* Don't send the position while stopped */ var_Get( p_input, "time", &val ); } else val.i_time = newval.i_time; libvlc_event_t event; event.type = libvlc_MediaPlayerTimeChanged; event.u.media_player_time_changed.new_time = val.i_time; libvlc_event_send( p_mi->p_event_manager, &event ); return VLC_SUCCESS;}/************************************************************************** * Create a Media Instance object **************************************************************************/libvlc_media_player_t *libvlc_media_player_new( libvlc_instance_t * p_libvlc_instance, libvlc_exception_t * p_e ){ libvlc_media_player_t * p_mi; if( !p_libvlc_instance ) { libvlc_exception_raise( p_e, "invalid libvlc instance" ); return NULL; } p_mi = malloc( sizeof(libvlc_media_player_t) ); if( !p_mi ) { libvlc_exception_raise( p_e, "Not enough memory" ); return NULL; } p_mi->p_md = NULL; p_mi->drawable = 0; p_mi->p_libvlc_instance = p_libvlc_instance; p_mi->p_input_thread = NULL; /* refcount strategy: * - All items created by _new start with a refcount set to 1 * - Accessor _release decrease the refcount by 1, if after that * operation the refcount is 0, the object is destroyed. * - Accessor _retain increase the refcount by 1 (XXX: to implement) */ p_mi->i_refcount = 1; p_mi->b_own_its_input_thread = true; /* object_lock strategy: * - No lock held in constructor * - Lock when accessing all variable this lock is held * - Lock when attempting to destroy the object the lock is also held */ vlc_mutex_init( &p_mi->object_lock );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -