]> git.sesse.net Git - vlc/blobdiff - src/control/media_player.c
libvlc: Export libvlc_media_player_get_input_thread().
[vlc] / src / control / media_player.c
index ad17ea048437fdcc9ad7d761676afba6076ec3f8..971474bc92aa7b4d5a518ad5e98f7add98df7ef6 100644 (file)
@@ -67,7 +67,7 @@ static void libvlc_media_player_destroy( libvlc_media_player_t *p_mi );
 #define register_event(a, b) __register_event(a, libvlc_MediaPlayer ## b)
 static inline void __register_event(libvlc_media_player_t *mp, libvlc_event_type_t type)
 {
-    libvlc_event_manager_register_event_type(mp->p_event_manager, type, NULL);
+    libvlc_event_manager_register_event_type(mp->p_event_manager, type);
 }
 
 static inline void lock(libvlc_media_player_t *mp)
@@ -80,12 +80,6 @@ static inline void unlock(libvlc_media_player_t *mp)
     vlc_mutex_unlock(&mp->object_lock);
 }
 
-static inline void clear_if_needed(libvlc_exception_t *e)
-{
-    if (libvlc_exception_raised(e))
-        libvlc_exception_clear(e);
-}
-
 /*
  * Release the associated input thread.
  *
@@ -155,6 +149,33 @@ input_thread_t *libvlc_get_input_thread( libvlc_media_player_t *p_mi,
     return p_input_thread;
 }
 
+/*
+ * Set the internal state of the media_player. (media player Internal)
+ *
+ * Function will lock the media_player.
+ */
+static void set_state( libvlc_media_player_t *p_mi, libvlc_state_t state,
+    bool b_locked )
+{
+    if(!b_locked)
+        lock(p_mi);
+    p_mi->state = state;
+    libvlc_media_t *media = p_mi->p_md;
+    if (media)
+        libvlc_media_retain(media);
+    if(!b_locked)
+        unlock(p_mi);
+
+
+    if (media) {
+        // Also set the state of the corresponding media
+        // This is strictly for convenience.
+        libvlc_media_set_state(media, state);
+
+        libvlc_media_release(media);
+    }
+}
+
 static int
 input_seekable_changed( vlc_object_t * p_this, char const * psz_cmd,
                         vlc_value_t oldval, vlc_value_t newval,
@@ -166,7 +187,6 @@ input_seekable_changed( vlc_object_t * p_this, char const * 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;
 
@@ -185,7 +205,6 @@ input_pausable_changed( vlc_object_t * p_this, char const * 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;
 
@@ -240,7 +259,7 @@ input_event_changed( vlc_object_t * p_this, char const * psz_cmd,
                 return VLC_SUCCESS;
         }
 
-        libvlc_media_set_state( p_mi->p_md, libvlc_state, NULL );
+        set_state( p_mi, libvlc_state, false );
         libvlc_event_send( p_mi->p_event_manager, &event );
     }
     else if( newval.i_int == INPUT_EVENT_ABORT )
@@ -248,7 +267,7 @@ input_event_changed( vlc_object_t * p_this, char const * psz_cmd,
         libvlc_state_t libvlc_state = libvlc_Stopped;
         event.type = libvlc_MediaPlayerStopped;
 
-        libvlc_media_set_state( p_mi->p_md, libvlc_state, NULL );
+        set_state( p_mi, libvlc_state, false );
         libvlc_event_send( p_mi->p_event_manager, &event );
     }
     else if( newval.i_int == INPUT_EVENT_POSITION )
@@ -265,14 +284,14 @@ input_event_changed( vlc_object_t * p_this, char const * psz_cmd,
         /* */
         event.type = libvlc_MediaPlayerTimeChanged;
         event.u.media_player_time_changed.new_time =
-                                               var_GetTime( p_input, "time" );
+           from_mtime(var_GetTime( p_input, "time" ));
         libvlc_event_send( p_mi->p_event_manager, &event );
     }
     else if( newval.i_int == INPUT_EVENT_LENGTH )
     {
         event.type = libvlc_MediaPlayerLengthChanged;
         event.u.media_player_length_changed.new_length =
-                                               var_GetTime( p_input, "length" );
+           from_mtime(var_GetTime( p_input, "length" ));
         libvlc_event_send( p_mi->p_event_manager, &event );
     }
 
@@ -336,18 +355,19 @@ libvlc_media_player_new( libvlc_instance_t *instance, libvlc_exception_t *e )
     mp->drawable.xid = 0;
     mp->drawable.hwnd = NULL;
     mp->drawable.nsobject = NULL;
+    mp->keyboard_events = mp->mouse_events = 1;
+    mp->state = libvlc_NothingSpecial;
     mp->p_libvlc_instance = instance;
     mp->p_input_thread = NULL;
     mp->p_input_resource = NULL;
     mp->i_refcount = 1;
-    vlc_mutex_init(&mp->object_lock);
-    mp->p_event_manager = libvlc_event_manager_new(mp, instance, e);
-    if (libvlc_exception_raised(e))
+    mp->p_event_manager = libvlc_event_manager_new(mp, instance);
+    if (unlikely(mp->p_event_manager == NULL))
     {
-        vlc_mutex_destroy(&mp->object_lock);
         free(mp);
         return NULL;
     }
+    vlc_mutex_init(&mp->object_lock);
 
     register_event(mp, NothingSpecial);
     register_event(mp, Opening);
@@ -359,6 +379,7 @@ libvlc_media_player_new( libvlc_instance_t *instance, libvlc_exception_t *e )
     register_event(mp, Backward);
     register_event(mp, EndReached);
     register_event(mp, EncounteredError);
+    register_event(mp, SeekableChanged);
 
     register_event(mp, PositionChanged);
     register_event(mp, TimeChanged);
@@ -369,6 +390,8 @@ libvlc_media_player_new( libvlc_instance_t *instance, libvlc_exception_t *e )
     /* Snapshot initialization */
     register_event(mp, SnapshotTaken);
 
+    register_event(mp, MediaChanged);
+
     /* Attach a var callback to the global object to provide the glue between
      * vout_thread that generates the event and media_player that re-emits it
      * with its own event manager
@@ -414,13 +437,18 @@ static void libvlc_media_player_destroy( libvlc_media_player_t *p_mi )
     var_DelCallback( p_mi->p_libvlc_instance->p_libvlc_int,
                      "snapshot-file", snapshot_was_taken, p_mi );
 
-    /* Release the input thread */
-    release_input_thread( p_mi, true );
+    /* If the input thread hasn't been already deleted it means
+     * that the owners didn't stop the thread before releasing it. */
+    assert(!p_mi->p_input_thread);
+
+    /* Fallback for those who don't use NDEBUG */
+    if (p_mi->p_input_thread)
+        release_input_thread(p_mi, true);
 
     if( p_mi->p_input_resource )
     {
         input_resource_Delete( p_mi->p_input_resource );
-        p_mi->p_input_resource = NULL;    
+        p_mi->p_input_resource = NULL;
     }
 
     libvlc_event_manager_release( p_mi->p_event_manager );
@@ -468,14 +496,8 @@ void libvlc_media_player_retain( libvlc_media_player_t *p_mi )
  **************************************************************************/
 void libvlc_media_player_set_media(
                             libvlc_media_player_t *p_mi,
-                            libvlc_media_t *p_md,
-                            libvlc_exception_t *p_e )
+                            libvlc_media_t *p_md )
 {
-    VLC_UNUSED(p_e);
-
-    if( !p_mi )
-        return;
-
     lock(p_mi);
 
     /* FIXME I am not sure if it is a user request or on die(eof/error)
@@ -485,8 +507,7 @@ void libvlc_media_player_set_media(
                           !p_mi->p_input_thread->b_eof &&
                           !p_mi->p_input_thread->b_error );
 
-    if( p_mi->p_md )
-        libvlc_media_set_state( p_mi->p_md, libvlc_NothingSpecial, p_e );
+    set_state( p_mi, libvlc_NothingSpecial, true );
 
     libvlc_media_release( p_mi->p_md );
 
@@ -505,18 +526,22 @@ void libvlc_media_player_set_media(
     p_mi->p_libvlc_instance = p_md->p_libvlc_instance;
 
     unlock(p_mi);
+
+    /* Send an event for the newly available media */
+    libvlc_event_t event;
+    event.type = libvlc_MediaPlayerMediaChanged;
+    event.u.media_player_media_changed.new_media = p_md;
+    libvlc_event_send( p_mi->p_event_manager, &event );
+
 }
 
 /**************************************************************************
  * Get the Media descriptor associated with the instance.
  **************************************************************************/
 libvlc_media_t *
-libvlc_media_player_get_media(
-                            libvlc_media_player_t *p_mi,
-                            libvlc_exception_t *p_e )
+libvlc_media_player_get_media( libvlc_media_player_t *p_mi )
 {
     libvlc_media_t *p_m;
-    VLC_UNUSED(p_e);
 
     lock(p_mi);
     p_m = p_mi->p_md;
@@ -530,12 +555,8 @@ libvlc_media_player_get_media(
  * Get the event Manager.
  **************************************************************************/
 libvlc_event_manager_t *
-libvlc_media_player_event_manager(
-                            libvlc_media_player_t *p_mi,
-                            libvlc_exception_t *p_e )
+libvlc_media_player_event_manager( libvlc_media_player_t *p_mi )
 {
-    VLC_UNUSED(p_e);
-
     return p_mi->p_event_manager;
 }
 
@@ -596,6 +617,11 @@ void libvlc_media_player_play( libvlc_media_player_t *p_mi,
     if( p_mi->drawable.nsobject != NULL )
         var_SetAddress( p_input_thread, "drawable-nsobject", p_mi->drawable.nsobject );
 
+    var_Create( p_input_thread, "keyboard-events", VLC_VAR_BOOL );
+    var_SetBool( p_input_thread, "keyboard-events", p_mi->keyboard_events );
+    var_Create( p_input_thread, "mouse-events", VLC_VAR_BOOL );
+    var_SetBool( p_input_thread, "mouse-events", p_mi->mouse_events );
+
     var_AddCallback( p_input_thread, "can-seek", input_seekable_changed, p_mi );
     var_AddCallback( p_input_thread, "can-pause", input_pausable_changed, p_mi );
     var_AddCallback( p_input_thread, "intf-event", input_event_changed, p_mi );
@@ -619,13 +645,13 @@ void libvlc_media_player_pause( libvlc_media_player_t *p_mi,
     if( !p_input_thread )
         return;
 
-    libvlc_state_t state = libvlc_media_player_get_state( p_mi, p_e );
+    libvlc_state_t state = libvlc_media_player_get_state( p_mi );
     if( state == libvlc_Playing || state == libvlc_Buffering )
     {
         if( libvlc_media_player_can_pause( p_mi, p_e ) )
             input_Control( p_input_thread, INPUT_SET_STATE, PAUSE_S );
         else
-            libvlc_media_player_stop( p_mi, p_e );
+            libvlc_media_player_stop( p_mi );
     }
     else
         input_Control( p_input_thread, INPUT_SET_STATE, PLAYING_S );
@@ -638,48 +664,42 @@ void libvlc_media_player_pause( libvlc_media_player_t *p_mi,
  *
  * Enter with lock held.
  **************************************************************************/
-int libvlc_media_player_is_playing( libvlc_media_player_t *p_mi,
-                                     libvlc_exception_t *p_e )
+int libvlc_media_player_is_playing( libvlc_media_player_t *p_mi )
 {
-    libvlc_state_t state = libvlc_media_player_get_state( p_mi, p_e );
+    libvlc_state_t state = libvlc_media_player_get_state( p_mi );
     return (libvlc_Playing == state) || (libvlc_Buffering == state);
 }
 
 /**************************************************************************
  * Stop playing.
  **************************************************************************/
-void libvlc_media_player_stop( libvlc_media_player_t *p_mi,
-                                 libvlc_exception_t *p_e )
+void libvlc_media_player_stop( libvlc_media_player_t *p_mi )
 {
-    libvlc_state_t state = libvlc_media_player_get_state( p_mi, p_e );
+    libvlc_state_t state = libvlc_media_player_get_state( p_mi );
+
+    lock(p_mi);
+    release_input_thread( p_mi, true ); /* This will stop the input thread */
+    unlock(p_mi);
 
-    if( state == libvlc_Playing ||
-        state == libvlc_Paused ||
-        state == libvlc_Buffering )
+    /* Force to go to stopped state, in case we were in Ended, or Error
+     * state. */
+    if( state != libvlc_Stopped )
     {
-        /* Send a stop notification event only if we are in playing,
-         * buffering or paused states */
-        libvlc_media_set_state( p_mi->p_md, libvlc_Stopped, p_e );
+        set_state( p_mi, libvlc_Stopped, false );
 
         /* Construct and send the event */
         libvlc_event_t event;
         event.type = libvlc_MediaPlayerStopped;
         libvlc_event_send( p_mi->p_event_manager, &event );
     }
-
-    lock(p_mi);
-    release_input_thread( p_mi, true ); /* This will stop the input thread */
-    unlock(p_mi);
 }
 
 /**************************************************************************
  * set_nsobject
  **************************************************************************/
 void libvlc_media_player_set_nsobject( libvlc_media_player_t *p_mi,
-                                        void * drawable,
-                                        libvlc_exception_t *p_e )
+                                        void * drawable )
 {
-    (void) p_e;
     p_mi->drawable.nsobject = drawable;
 }
 
@@ -695,10 +715,8 @@ void * libvlc_media_player_get_nsobject( libvlc_media_player_t *p_mi )
  * set_agl
  **************************************************************************/
 void libvlc_media_player_set_agl( libvlc_media_player_t *p_mi,
-                                      uint32_t drawable,
-                                      libvlc_exception_t *p_e )
+                                  uint32_t drawable )
 {
-    (void) p_e;
     p_mi->drawable.agl = drawable;
 }
 
@@ -714,10 +732,8 @@ uint32_t libvlc_media_player_get_agl( libvlc_media_player_t *p_mi )
  * set_xwindow
  **************************************************************************/
 void libvlc_media_player_set_xwindow( libvlc_media_player_t *p_mi,
-                                      uint32_t drawable,
-                                      libvlc_exception_t *p_e )
+                                      uint32_t drawable )
 {
-    (void) p_e;
     p_mi->drawable.xid = drawable;
 }
 
@@ -733,10 +749,8 @@ uint32_t libvlc_media_player_get_xwindow( libvlc_media_player_t *p_mi )
  * set_hwnd
  **************************************************************************/
 void libvlc_media_player_set_hwnd( libvlc_media_player_t *p_mi,
-                                   void *drawable,
-                                   libvlc_exception_t *p_e )
+                                   void *drawable )
 {
-    (void) p_e;
     p_mi->drawable.hwnd = drawable;
 }
 
@@ -762,10 +776,10 @@ libvlc_time_t libvlc_media_player_get_length(
     if( !p_input_thread )
         return -1;
 
-    i_time = var_GetTime( p_input_thread, "length" );
+    i_time = from_mtime(var_GetTime( p_input_thread, "length" ));
     vlc_object_release( p_input_thread );
 
-    return (i_time+500LL)/1000LL;
+    return i_time;
 }
 
 libvlc_time_t libvlc_media_player_get_time(
@@ -779,9 +793,9 @@ libvlc_time_t libvlc_media_player_get_time(
     if( !p_input_thread )
         return -1;
 
-    i_time = var_GetTime( p_input_thread , "time" );
+    i_time = from_mtime(var_GetTime( p_input_thread , "time" ));
     vlc_object_release( p_input_thread );
-    return (i_time+500LL)/1000LL;
+    return i_time;
 }
 
 void libvlc_media_player_set_time(
@@ -795,7 +809,7 @@ void libvlc_media_player_set_time(
     if( !p_input_thread )
         return;
 
-    var_SetTime( p_input_thread, "time", i_time*1000LL );
+    var_SetTime( p_input_thread, "time", to_mtime(i_time) );
     vlc_object_release( p_input_thread );
 }
 
@@ -1013,18 +1027,16 @@ float libvlc_media_player_get_fps(
 int libvlc_media_player_will_play( libvlc_media_player_t *p_mi,
                                      libvlc_exception_t *p_e)
 {
+    bool b_will_play;
     input_thread_t *p_input_thread =
                             libvlc_get_input_thread ( p_mi, p_e);
     if ( !p_input_thread )
         return false;
 
-    if ( !p_input_thread->b_die && !p_input_thread->b_dead )
-    {
-        vlc_object_release( p_input_thread );
-        return true;
-    }
+    b_will_play = !p_input_thread->b_die && !p_input_thread->b_dead;
     vlc_object_release( p_input_thread );
-    return false;
+
+    return b_will_play;
 }
 
 void libvlc_media_player_set_rate(
@@ -1048,7 +1060,7 @@ void libvlc_media_player_set_rate(
         return;
     }
 
-    var_SetInteger( p_input_thread, "rate", 1000.0f/rate );
+    var_SetFloat( p_input_thread, "rate", rate );
     vlc_object_release( p_input_thread );
 }
 
@@ -1057,49 +1069,31 @@ float libvlc_media_player_get_rate(
                                  libvlc_exception_t *p_e )
 {
     input_thread_t *p_input_thread;
-    int i_rate;
+    float f_rate;
     bool b_can_rewind;
 
     p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
     if( !p_input_thread )
         return 0.0;  /* rate < 0 indicates rewind */
 
-    i_rate = var_GetInteger( p_input_thread, "rate" );
+    f_rate = var_GetFloat( p_input_thread, "rate" );
     b_can_rewind = var_GetBool( p_input_thread, "can-rewind" );
-    if( i_rate < 0 && !b_can_rewind )
+    /* FIXME: why are negative values forbidden ?? (rewinding) */
+    if( f_rate < 0 && !b_can_rewind )
     {
         vlc_object_release( p_input_thread );
         return 0.0;
     }
     vlc_object_release( p_input_thread );
 
-    return (float)1000.0f/i_rate;
+    return f_rate;
 }
 
-libvlc_state_t libvlc_media_player_get_state(
-                                 libvlc_media_player_t *p_mi,
-                                 libvlc_exception_t *p_e )
+libvlc_state_t libvlc_media_player_get_state( libvlc_media_player_t *p_mi )
 {
-    input_thread_t *p_input_thread;
-    libvlc_state_t state = libvlc_Ended;
-
-    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 */
-        clear_if_needed(p_e);
-        return state;
-    }
-
-    state = libvlc_media_get_state( p_mi->p_md, NULL );
-    if( state == libvlc_Playing )
-    {
-        float caching;
-        caching = var_GetFloat( p_input_thread, "cache" );
-        if( caching > 0.0 && caching < 1.0 )
-            state = libvlc_Buffering;
-    }
-    vlc_object_release( p_input_thread );
+    lock(p_mi);
+    libvlc_state_t state = p_mi->state;
+    unlock(p_mi);
     return state;
 }
 
@@ -1229,3 +1223,15 @@ void libvlc_media_player_next_frame( libvlc_media_player_t *p_mi, libvlc_excepti
         libvlc_printerr( "No active input" );
     }
 }
+
+/**************************************************************************
+ * get_input_thread (Public API version)
+ **************************************************************************/
+struct input_thread_t *libvlc_media_player_get_input_thread( libvlc_media_player_t *player )
+{
+    libvlc_exception_t e;
+    libvlc_exception_init(&e);
+    input_thread_t *input = libvlc_get_input_thread(player, &e);
+    clear_if_needed(&e);
+    return input;
+}