* 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 "libvlc_internal.h"
#include "libvlc.h"
+static int
+input_state_changed( vlc_object_t * p_this, char const * psz_cmd,
+ vlc_value_t oldval, vlc_value_t newval,
+ void * p_userdata );
+static int
+input_seekable_changed( vlc_object_t * p_this, char const * psz_cmd,
+ vlc_value_t oldval, vlc_value_t newval,
+ void * p_userdata );
+static int
+input_pausable_changed( vlc_object_t * p_this, char const * psz_cmd,
+ vlc_value_t oldval, vlc_value_t newval,
+ void * p_userdata );
+static int
+input_position_changed( vlc_object_t * p_this, char const * psz_cmd,
+ vlc_value_t oldval, vlc_value_t newval,
+ void * p_userdata );
+static int
+input_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_Opening,
+ [OPENING_S] = libvlc_Opening,
+ [BUFFERING_S] = libvlc_Buffering,
+ [PLAYING_S] = libvlc_Playing,
+ [PAUSE_S] = libvlc_Paused,
+ [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_Stopped;
+
+ return vlc_to_libvlc_state_array[vlc_state];
+}
+
/*
* Release the associated input thread
*
if( !p_mi || p_mi->i_input_id == -1 )
return;
- p_input_thread = (input_thread_t*)vlc_object_get(
- p_mi->p_libvlc_instance->p_libvlc_int,
- p_mi->i_input_id );
+ p_input_thread = (input_thread_t*)vlc_object_get( p_mi->i_input_id );
p_mi->i_input_id = -1;
if( !p_input_thread )
return;
- /* release for previous vlc_object_get */
- vlc_object_release( p_input_thread );
-
- /* release for initial p_input_thread yield (see _new()) */
- vlc_object_release( p_input_thread );
/* No one is tracking this input_thread appart us. Destroy it */
if( p_mi->b_own_its_input_thread )
{
+ var_DelCallback( p_input_thread, "state", 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 );
+
var_Destroy( p_input_thread, "drawable" );
- input_DestroyThread( p_input_thread );
}
else
{
* revert that here. This will be deleted with the playlist API */
vlc_object_release( p_input_thread );
}
+
+ /* release for previous vlc_object_get */
+ vlc_object_release( p_input_thread );
}
/*
{
input_thread_t *p_input_thread;
+ if ( !p_mi )
+ {
+ RAISENULL( "Input is NULL" );
+ }
+
vlc_mutex_lock( &p_mi->object_lock );
if( !p_mi || p_mi->i_input_id == -1 )
RAISENULL( "Input is NULL" );
}
- p_input_thread = (input_thread_t*)vlc_object_get(
- p_mi->p_libvlc_instance->p_libvlc_int,
- p_mi->i_input_id );
+ p_input_thread = (input_thread_t*)vlc_object_get( p_mi->i_input_id );
if( !p_input_thread )
{
vlc_mutex_unlock( &p_mi->object_lock );
vlc_value_t oldval, vlc_value_t newval,
void * p_userdata )
{
+ VLC_UNUSED(oldval);
+ VLC_UNUSED(p_this);
+ VLC_UNUSED(psz_cmd);
libvlc_media_instance_t * p_mi = p_userdata;
libvlc_event_t event;
+ libvlc_event_type_t type = newval.i_int;
- if( newval.i_int == oldval.i_int )
- return VLC_SUCCESS; /* No change since last time, don't propagate */
-
- switch ( newval.i_int )
+ switch ( type )
{
case END_S:
+ libvlc_media_descriptor_set_state( p_mi->p_md, libvlc_NothingSpecial, NULL);
event.type = libvlc_MediaInstanceReachedEnd;
break;
case PAUSE_S:
+ libvlc_media_descriptor_set_state( p_mi->p_md, libvlc_Playing, NULL);
event.type = libvlc_MediaInstancePaused;
break;
case PLAYING_S:
+ libvlc_media_descriptor_set_state( p_mi->p_md, libvlc_Playing, NULL);
event.type = libvlc_MediaInstancePlayed;
break;
+ case ERROR_S:
+ libvlc_media_descriptor_set_state( p_mi->p_md, libvlc_Error, NULL);
+ event.type = libvlc_MediaInstanceEncounteredError;
+ break;
default:
return VLC_SUCCESS;
}
return VLC_SUCCESS;
}
+static int
+input_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_instance_t * p_mi = p_userdata;
+ libvlc_event_t event;
+
+ libvlc_media_descriptor_set_state( p_mi->p_md, libvlc_NothingSpecial, NULL);
+ event.type = libvlc_MediaInstanceSeekableChanged;
+ event.u.media_instance_seekable_changed.new_seekable = newval.b_bool;
+
+ libvlc_event_send( p_mi->p_event_manager, &event );
+ return VLC_SUCCESS;
+}
+
+static int
+input_pausable_changed( vlc_object_t * p_this, char const * psz_cmd,
+ vlc_value_t oldval, vlc_value_t newval,
+ void * p_userdata )
+{
+ VLC_UNUSED(oldval);
+ VLC_UNUSED(p_this);
+ VLC_UNUSED(psz_cmd);
+ libvlc_media_instance_t * p_mi = p_userdata;
+ libvlc_event_t event;
+
+ libvlc_media_descriptor_set_state( p_mi->p_md, libvlc_NothingSpecial, NULL);
+ event.type = libvlc_MediaInstancePausableChanged;
+ event.u.media_instance_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)
*/
vlc_value_t oldval, vlc_value_t newval,
void * p_userdata )
{
+ VLC_UNUSED(oldval);
libvlc_media_instance_t * p_mi = p_userdata;
vlc_value_t val;
-
- if (!strcmp(psz_cmd, "intf" /* "-change" no need to go further */))
+
+ 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, "position", &val );
- if ((val.i_time % I64C(500000)) != 0)
- return VLC_SUCCESS; /* No need to have a better precision */
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_MediaInstancePositionChanged;
- event.u.media_instance_position_changed.new_position = val.i_time;
+ event.u.media_instance_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 int
+input_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_instance_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_MediaInstanceTimeChanged;
+ event.u.media_instance_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_event_manager_register_event_type( p_mi->p_event_manager,
libvlc_MediaInstanceReachedEnd, p_e );
+ libvlc_event_manager_register_event_type( p_mi->p_event_manager,
+ libvlc_MediaInstanceEncounteredError, p_e );
libvlc_event_manager_register_event_type( p_mi->p_event_manager,
libvlc_MediaInstancePaused, p_e );
libvlc_event_manager_register_event_type( p_mi->p_event_manager,
libvlc_MediaInstancePlayed, p_e );
libvlc_event_manager_register_event_type( p_mi->p_event_manager,
libvlc_MediaInstancePositionChanged, p_e );
+ libvlc_event_manager_register_event_type( p_mi->p_event_manager,
+ libvlc_MediaInstanceTimeChanged, p_e );
+ libvlc_event_manager_register_event_type( p_mi->p_event_manager,
+ libvlc_MediaInstanceSeekableChanged, p_e );
+ libvlc_event_manager_register_event_type( p_mi->p_event_manager,
+ libvlc_MediaInstancePausableChanged, p_e );
return p_mi;
}
release_input_thread( p_mi );
+ if( p_mi->p_md )
+ libvlc_media_descriptor_set_state( p_mi->p_md, libvlc_NothingSpecial, NULL );
+
libvlc_media_descriptor_release( p_mi->p_md );
if( !p_md )
return;
}
- p_input_thread = input_CreateThread( p_mi->p_libvlc_instance->p_libvlc_int,
- p_mi->p_md->p_input_item );
- p_mi->i_input_id = p_input_thread->i_object_id;
+ p_mi->i_input_id = input_Read( p_mi->p_libvlc_instance->p_libvlc_int,
+ p_mi->p_md->p_input_item, VLC_FALSE );
+
+ p_input_thread = (input_thread_t*)vlc_object_get( p_mi->i_input_id );
+
+ if( !p_input_thread )
+ {
+ return;
+ vlc_mutex_unlock( &p_mi->object_lock );
+ }
if( p_mi->drawable )
{
var_Set( p_input_thread, "drawable", val );
}
var_AddCallback( p_input_thread, "state", input_state_changed, p_mi );
+ var_AddCallback( p_input_thread, "seekable", input_seekable_changed, p_mi );
+ var_AddCallback( p_input_thread, "pausable", input_pausable_changed, p_mi );
var_AddCallback( p_input_thread, "intf-change", input_position_changed, p_mi );
+ var_AddCallback( p_input_thread, "intf-change", input_time_changed, p_mi );
- /* will be released in media_instance_release() */
- vlc_object_yield( p_input_thread );
-
+ vlc_object_release( p_input_thread );
vlc_mutex_unlock( &p_mi->object_lock );
}
if( !p_input_thread )
return;
- input_Control( p_input_thread, INPUT_SET_STATE, PAUSE_S );
+ int state = var_GetInteger( p_input_thread, "state" );
+
+ if( state == PLAYING_S )
+ {
+ if( libvlc_media_instance_can_pause( p_mi, p_e ) )
+ input_Control( p_input_thread, INPUT_SET_STATE, PAUSE_S );
+ else
+ libvlc_media_instance_stop( p_mi, p_e );
+ }
+ else
+ input_Control( p_input_thread, INPUT_SET_STATE, PLAYING_S );
+
vlc_object_release( p_input_thread );
}
libvlc_drawable_t drawable,
libvlc_exception_t *p_e )
{
+ (void)p_e;
p_mi->drawable = drawable;
}
+/**************************************************************************
+ * Get Drawable
+ **************************************************************************/
+libvlc_drawable_t
+libvlc_media_instance_get_drawable ( libvlc_media_instance_t *p_mi, libvlc_exception_t *p_e )
+{
+ (void)p_e;
+ return p_mi->drawable;
+}
+
/**************************************************************************
* Getters for stream information
**************************************************************************/
-vlc_int64_t libvlc_media_instance_get_length(
+libvlc_time_t libvlc_media_instance_get_length(
libvlc_media_instance_t *p_mi,
libvlc_exception_t *p_e )
{
return (val.i_time+500LL)/1000LL;
}
-vlc_int64_t libvlc_media_instance_get_time(
+libvlc_time_t libvlc_media_instance_get_time(
libvlc_media_instance_t *p_mi,
libvlc_exception_t *p_e )
{
void libvlc_media_instance_set_time(
libvlc_media_instance_t *p_mi,
- vlc_int64_t time,
+ libvlc_time_t time,
libvlc_exception_t *p_e )
{
input_thread_t *p_input_thread;
return (float)1000.0f/val.i_int;
}
-static const libvlc_state_t vlc_to_libvlc_state[] =
-{
- [INIT_S] = libvlc_Opening,
- [OPENING_S] = libvlc_Opening,
- [BUFFERING_S] = libvlc_Buffering,
- [PLAYING_S] = libvlc_Playing,
- [PAUSE_S] = libvlc_Paused,
- [END_S] = libvlc_Ended,
- [ERROR_S] = libvlc_Error,
-};
-
libvlc_state_t libvlc_media_instance_get_state(
libvlc_media_instance_t *p_mi,
libvlc_exception_t *p_e )
p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
if ( !p_input_thread )
+ {
+ /* We do return the right value, no need to throw an exception */
+ if( libvlc_exception_raised( p_e ) )
+ libvlc_exception_clear( p_e );
return libvlc_Stopped;
+ }
var_Get( p_input_thread, "state", &val );
vlc_object_release( p_input_thread );
- if( val.i_int < 0 || val.i_int > 6 )
- return libvlc_Stopped;
+ return vlc_to_libvlc_state(val.i_int);
+}
+
+vlc_bool_t libvlc_media_instance_is_seekable(
+ libvlc_media_instance_t *p_mi,
+ libvlc_exception_t *p_e )
+{
+ input_thread_t *p_input_thread;
+ vlc_value_t val;
+
+ p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
+ if ( !p_input_thread )
+ {
+ /* We do return the right value, no need to throw an exception */
+ if( libvlc_exception_raised( p_e ) )
+ libvlc_exception_clear( p_e );
+ return VLC_FALSE;
+ }
+ var_Get( p_input_thread, "seekable", &val );
+ vlc_object_release( p_input_thread );
+
+ return val.b_bool;
+}
+
+vlc_bool_t libvlc_media_instance_can_pause(
+ libvlc_media_instance_t *p_mi,
+ libvlc_exception_t *p_e )
+{
+ input_thread_t *p_input_thread;
+ vlc_value_t val;
+
+ p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
+ if ( !p_input_thread )
+ {
+ /* We do return the right value, no need to throw an exception */
+ if( libvlc_exception_raised( p_e ) )
+ libvlc_exception_clear( p_e );
+ return VLC_FALSE;
+ }
+ var_Get( p_input_thread, "can-pause", &val );
+ vlc_object_release( p_input_thread );
- return vlc_to_libvlc_state[val.i_int];
+ return val.b_bool;
}