]> git.sesse.net Git - vlc/blobdiff - src/control/media_player.c
Unify libvlc_state_t, input_state_e, mediacontrol_PlayerStatus and libvlc_event_type_t.
[vlc] / src / control / media_player.c
index a38df319e7b810a2af647fc7bbb2c2411452cee4..689871db31339c85b54b48b07987eeafe07a2a9f 100644 (file)
 #include <vlc/libvlc.h>
 #include <vlc_demux.h>
 #include <vlc_input.h>
+#include <vlc_vout.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 void
+input_state_changed( const vlc_event_t * event, 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,
@@ -51,18 +51,21 @@ input_time_changed( vlc_object_t * p_this, char const * psz_cmd,
 
 static const libvlc_state_t vlc_to_libvlc_state_array[] =
 {
-    [INIT_S]        = libvlc_Opening,
+    [INIT_S]        = libvlc_NothingSpecial,
     [OPENING_S]     = libvlc_Opening,
-    [BUFFERING_S]   = libvlc_Buffering,    
-    [PLAYING_S]     = libvlc_Playing,    
-    [PAUSE_S]       = libvlc_Paused,    
-    [END_S]         = libvlc_Ended,    
-    [ERROR_S]       = libvlc_Error,    
+    [BUFFERING_S]   = libvlc_Buffering,
+    [PLAYING_S]     = libvlc_Playing,
+    [PAUSE_S]       = libvlc_Paused,
+    [END_S]         = libvlc_Ended,
+    [FORWARD_S]     = libvlc_Forward,
+    [BACKWARD_S]    = libvlc_Backward,
+    [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 libvlc_Ended;
 
     return vlc_to_libvlc_state_array[vlc_state];
 }
@@ -84,7 +87,8 @@ static void release_input_thread( libvlc_media_player_t *p_mi )
     /* 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 );
+        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 );
@@ -113,7 +117,7 @@ input_thread_t *libvlc_get_input_thread( libvlc_media_player_t *p_mi,
     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 )
@@ -131,44 +135,60 @@ input_thread_t *libvlc_get_input_thread( libvlc_media_player_t *p_mi,
 }
 
 /*
- * input_state_changed (Private) (input var "state" Callback)
+ * input_state_changed (Private) (vlc_InputStateChanged callback)
  */
-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 void
+input_state_changed( const vlc_event_t * event, 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_event_type_t type = newval.i_int;
+    libvlc_event_t forwarded_event;
+    libvlc_event_type_t type = event->u.input_state_changed.new_state;
 
     switch ( type )
     {
-        case END_S:
+        case INIT_S:
             libvlc_media_set_state( p_mi->p_md, libvlc_NothingSpecial, NULL);
-            event.type = libvlc_MediaPlayerEndReached;
+            forwarded_event.type = libvlc_MediaPlayerNothingSpecial;
             break;
-        case PAUSE_S:
-            libvlc_media_set_state( p_mi->p_md, libvlc_Playing, NULL);
-            event.type = libvlc_MediaPlayerPaused;
+        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);
-            event.type = libvlc_MediaPlayerPlayed;
+            forwarded_event.type = libvlc_MediaPlayerPlayed;
+            break;
+        case PAUSE_S:
+            libvlc_media_set_state( p_mi->p_md, libvlc_Paused, NULL);
+            forwarded_event.type = libvlc_MediaPlayerPaused;
+            break;
+        case END_S:
+            libvlc_media_set_state( p_mi->p_md, libvlc_Ended, NULL);
+            forwarded_event.type = libvlc_MediaPlayerEndReached;
+            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 ERROR_S:
             libvlc_media_set_state( p_mi->p_md, libvlc_Error, NULL);
-            event.type = libvlc_MediaPlayerEncounteredError;
+            forwarded_event.type = libvlc_MediaPlayerEncounteredError;
             break;
+
         default:
-            return VLC_SUCCESS;
+            return;
     }
 
-    libvlc_event_send( p_mi->p_event_manager, &event );
-    return VLC_SUCCESS;
+    libvlc_event_send( p_mi->p_event_manager, &forwarded_event );
+    return;
 }
 
 static int
@@ -257,7 +277,7 @@ input_time_changed( vlc_object_t * p_this, char const * psz_cmd,
     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 */
@@ -290,6 +310,11 @@ libvlc_media_player_new( libvlc_instance_t * p_libvlc_instance,
     }
 
     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;
@@ -315,15 +340,24 @@ libvlc_media_player_new( libvlc_instance_t * p_libvlc_instance,
     }
 
     libvlc_event_manager_register_event_type( p_mi->p_event_manager,
-            libvlc_MediaPlayerEndReached, p_e );
+            libvlc_MediaPlayerNothingSpecial, p_e );
     libvlc_event_manager_register_event_type( p_mi->p_event_manager,
-            libvlc_MediaPlayerStopped, p_e );
+            libvlc_MediaPlayerOpening, p_e );
     libvlc_event_manager_register_event_type( p_mi->p_event_manager,
-            libvlc_MediaPlayerEncounteredError, p_e );
+            libvlc_MediaPlayerBuffering, p_e );
+    libvlc_event_manager_register_event_type( p_mi->p_event_manager,
+            libvlc_MediaPlayerPlaying, p_e );
     libvlc_event_manager_register_event_type( p_mi->p_event_manager,
             libvlc_MediaPlayerPaused, p_e );
     libvlc_event_manager_register_event_type( p_mi->p_event_manager,
-            libvlc_MediaPlayerPlayed, p_e );
+            libvlc_MediaPlayerEndReached, p_e );
+    libvlc_event_manager_register_event_type( p_mi->p_event_manager,
+            libvlc_MediaPlayerForward, p_e );
+    libvlc_event_manager_register_event_type( p_mi->p_event_manager,
+            libvlc_MediaPlayerBackward, p_e );
+    libvlc_event_manager_register_event_type( p_mi->p_event_manager,
+            libvlc_MediaPlayerEncounteredError, p_e );
+
     libvlc_event_manager_register_event_type( p_mi->p_event_manager,
             libvlc_MediaPlayerPositionChanged, p_e );
     libvlc_event_manager_register_event_type( p_mi->p_event_manager,
@@ -438,7 +472,7 @@ void libvlc_media_player_release( libvlc_media_player_t *p_mi )
         return;
 
     vlc_mutex_lock( &p_mi->object_lock );
+
     p_mi->i_refcount--;
 
     if( p_mi->i_refcount > 0 )
@@ -452,7 +486,7 @@ void libvlc_media_player_release( libvlc_media_player_t *p_mi )
     release_input_thread( p_mi );
 
     libvlc_event_manager_release( p_mi->p_event_manager );
+
     libvlc_media_release( p_mi->p_md );
 
     free( p_mi );
@@ -477,7 +511,7 @@ void libvlc_media_player_set_media(
                             libvlc_media_t *p_md,
                             libvlc_exception_t *p_e )
 {
-    (void)p_e;
+    VLC_UNUSED(p_e);
 
     if( !p_mi )
         return;
@@ -487,7 +521,7 @@ void libvlc_media_player_set_media(
     release_input_thread( p_mi );
 
     if( p_mi->p_md )
-        libvlc_media_set_state( p_mi->p_md, libvlc_NothingSpecial, NULL );
+        libvlc_media_set_state( p_mi->p_md, libvlc_NothingSpecial, p_e );
 
     libvlc_media_release( p_mi->p_md );
 
@@ -500,7 +534,7 @@ void libvlc_media_player_set_media(
 
     libvlc_media_retain( p_md );
     p_mi->p_md = p_md;
+
     /* The policy here is to ignore that we were created using a different
      * libvlc_instance, because we don't really care */
     p_mi->p_libvlc_instance = p_md->p_libvlc_instance;
@@ -516,7 +550,7 @@ libvlc_media_player_get_media(
                             libvlc_media_player_t *p_mi,
                             libvlc_exception_t *p_e )
 {
-    (void)p_e;
+    VLC_UNUSED(p_e);
 
     if( !p_mi->p_md )
         return NULL;
@@ -533,7 +567,7 @@ libvlc_media_player_event_manager(
                             libvlc_media_player_t *p_mi,
                             libvlc_exception_t *p_e )
 {
-    (void)p_e;
+    VLC_UNUSED(p_e);
 
     return p_mi->p_event_manager;
 }
@@ -558,7 +592,7 @@ void libvlc_media_player_play( libvlc_media_player_t *p_mi,
     libvlc_exception_clear( p_e );
 
     vlc_mutex_lock( &p_mi->object_lock );
+
     if( !p_mi->p_md )
     {
         libvlc_exception_raise( p_e, "no associated media descriptor" );
@@ -585,7 +619,10 @@ void libvlc_media_player_play( libvlc_media_player_t *p_mi,
         var_Create( p_input_thread, "drawable", VLC_VAR_DOINHERIT );
         var_Set( p_input_thread, "drawable", val );
     }
-    var_AddCallback( p_input_thread, "state", input_state_changed, p_mi );
+
+    vlc_event_manager_t * p_em = input_get_event_manager( p_input_thread );
+    vlc_event_attach( p_em, vlc_InputStateChanged, 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 );
@@ -605,9 +642,9 @@ void libvlc_media_player_pause( libvlc_media_player_t *p_mi,
     if( !p_input_thread )
         return;
 
-    int state = var_GetInteger( p_input_thread, "state" );
+    libvlc_state_t state = libvlc_media_player_get_state( p_mi, p_e );
 
-    if( state == PLAYING_S )
+    if( state == libvlc_Playing )
     {
         if( libvlc_media_player_can_pause( p_mi, p_e ) )
             input_Control( p_input_thread, INPUT_SET_STATE, PAUSE_S );
@@ -626,6 +663,19 @@ void libvlc_media_player_pause( libvlc_media_player_t *p_mi,
 void libvlc_media_player_stop( libvlc_media_player_t *p_mi,
                                  libvlc_exception_t *p_e )
 {
+    libvlc_state_t state = libvlc_media_player_get_state( p_mi, p_e );
+
+    if( state == libvlc_Playing || state == libvlc_Paused )
+    {
+        /* Send a stop notification event only of we are in playing or paused states */
+        libvlc_media_set_state( p_mi->p_md, libvlc_Ended, p_e );
+
+        /* Construct and send the event */
+        libvlc_event_t event;
+        event.type = libvlc_MediaPlayerEndReached;
+        libvlc_event_send( p_mi->p_event_manager, &event );
+    }
+
     if( p_mi->b_own_its_input_thread )
     {
         vlc_mutex_lock( &p_mi->object_lock );
@@ -642,23 +692,36 @@ void libvlc_media_player_stop( libvlc_media_player_t *p_mi,
         input_StopThread( p_input_thread );
         vlc_object_release( p_input_thread );
     }
-
-    /* Send a stop notification event */
-    libvlc_event_t event;
-    libvlc_media_set_state( p_mi->p_md, libvlc_Stopped, NULL);
-    event.type = libvlc_MediaPlayerStopped;
-    libvlc_event_send( p_mi->p_event_manager, &event );
 }
 
 /**************************************************************************
  * Set Drawable
  **************************************************************************/
 void libvlc_media_player_set_drawable( libvlc_media_player_t *p_mi,
-                                         libvlc_drawable_t drawable,
-                                         libvlc_exception_t *p_e )
+                                       libvlc_drawable_t drawable,
+                                       libvlc_exception_t *p_e )
 {
-    (void)p_e;
+    input_thread_t *p_input_thread;
+    vout_thread_t *p_vout = NULL;
+
     p_mi->drawable = drawable;
+
+    /* Allow on the fly drawable changing. This is tricky has this may
+     * not be supported by every vout. We though can't disable it
+     * because of some creepy drawable type that are not flexible enough
+     * (Win32 HWND for instance) */
+    p_input_thread = libvlc_get_input_thread( p_mi, p_e );
+    if( !p_input_thread ) return;
+
+    p_vout = vlc_object_find( p_input_thread, VLC_OBJECT_VOUT, FIND_CHILD );
+    if( !p_vout )
+        libvlc_exception_raise( p_e, "No active video output" );
+    else
+    {
+        vout_Control( p_vout , VOUT_REPARENT, drawable);
+        vlc_object_release( p_vout );
+    }
+    vlc_object_release( p_input_thread );
 }
 
 /**************************************************************************
@@ -667,7 +730,7 @@ void libvlc_media_player_set_drawable( libvlc_media_player_t *p_mi,
 libvlc_drawable_t
 libvlc_media_player_get_drawable ( libvlc_media_player_t *p_mi, libvlc_exception_t *p_e )
 {
-    (void)p_e;
+    VLC_UNUSED(p_e);
     return p_mi->drawable;
 }
 
@@ -893,7 +956,7 @@ libvlc_state_t libvlc_media_player_get_state(
         /* 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;
+        return libvlc_Ended;
     }
 
     var_Get( p_input_thread, "state", &val );