[vlc-devel] [PATCH] libvlc: fix MediaPlayerESSelected events not sent

Thomas Guillem thomas at gllm.fr
Fri Mar 31 15:25:27 CEST 2017


This event was sent only when an ES was changed by libvlc. It was not sent when
an ES was changed by the input thread. To fix this issue, listen to the
INPUT_EVENT_ES input event (that is sent when an ES is added/deleted/selected)
to detect an ES selection change.

We don't want to trigger callbacks for "video-es"/"audio-es"/"spu-es" variables
from the input_thread since it's also listening to these callbacks and we want
to avoid a selecting busy loop.
---
 lib/media_player.c          | 65 ++++++++++++++++++++++++---------------------
 lib/media_player_internal.h |  1 +
 2 files changed, 36 insertions(+), 30 deletions(-)

diff --git a/lib/media_player.c b/lib/media_player.c
index 2c5aa727fb..6ab47254f7 100644
--- a/lib/media_player.c
+++ b/lib/media_player.c
@@ -65,11 +65,6 @@ input_es_changed( vlc_object_t * p_this, char const * psz_cmd,
                   void *p_userdata);
 
 static int
-input_es_selected( vlc_object_t * p_this, char const * psz_cmd,
-                   vlc_value_t oldval, vlc_value_t newval,
-                   void * p_userdata );
-
-static int
 corks_changed(vlc_object_t *obj, const char *name, vlc_value_t old,
               vlc_value_t cur, void *opaque);
 
@@ -411,6 +406,39 @@ input_event_changed( vlc_object_t * p_this, char const * psz_cmd,
         event.u.media_player_chapter_changed.new_chapter = var_GetInteger( p_input, "chapter" );
         libvlc_event_send( p_mi->p_event_manager, &event );
     }
+    else if ( newval.i_int == INPUT_EVENT_ES )
+    {
+        /* Send ESSelected events from this callback ("intf-event") and not
+         * from "audio-es", "video-es", "spu-es" callbacks. Indeed, these
+         * callbacks are not triggered when the input_thread changes an ES
+         * while this callback is. */
+
+        int new_es[3] = { -2, -2, -2 }; /* -1 is reserved for deselect */
+        static const char *es_names[3] = { "audio-es", "video-es", "spu-es" };
+        static const int es_types[3] = { libvlc_track_audio, libvlc_track_video,
+                                         libvlc_track_text };
+        /* Check if an es selection changed */
+        lock( p_mi );
+        for( int i = 0; i < 3; ++i ) /* for audio, video, spu */
+        {
+            int current_es = var_GetInteger( p_input, es_names[i] );
+            if( current_es != p_mi->selected_es[i] )
+                new_es[i] = p_mi->selected_es[i] = current_es;
+        }
+        unlock( p_mi );
+
+        /* Send the ESSelected event for each ES that were newly selected */
+        for( int i = 0; i < 3; ++i ) /* for audio, video, spu */
+        {
+            if( new_es[i] != -2 )
+            {
+                event.type = libvlc_MediaPlayerESSelected;
+                event.u.media_player_es_changed.i_type = es_types[i];
+                event.u.media_player_es_changed.i_id = new_es[i];
+                libvlc_event_send( p_mi->p_event_manager, &event );
+            }
+        }
+    }
 
     return VLC_SUCCESS;
 }
@@ -475,25 +503,6 @@ static int input_es_changed( vlc_object_t *p_this,
     return VLC_SUCCESS;
 }
 
-static int
-input_es_selected( vlc_object_t * p_this, char const * psz_cmd,
-                   vlc_value_t oldval, vlc_value_t newval,
-                   void * p_userdata )
-{
-    VLC_UNUSED(p_this);
-    VLC_UNUSED(oldval);
-    libvlc_media_player_t *mp = p_userdata;
-    libvlc_event_t event;
-
-    event.type = libvlc_MediaPlayerESSelected;
-    event.u.media_player_es_changed.i_type = track_type_from_name(psz_cmd);
-    event.u.media_player_es_changed.i_id = newval.i_int;
-
-    libvlc_event_send(mp->p_event_manager, &event);
-
-    return VLC_SUCCESS;
-}
-
 /**************************************************************************
  * Snapshot Taken Event.
  *
@@ -916,9 +925,6 @@ static void add_es_callbacks( input_thread_t *p_input_thread, libvlc_media_playe
     var_AddListCallback( p_input_thread, "video-es", input_es_changed, p_mi );
     var_AddListCallback( p_input_thread, "audio-es", input_es_changed, p_mi );
     var_AddListCallback( p_input_thread, "spu-es", input_es_changed, p_mi );
-    var_AddCallback( p_input_thread, "video-es", input_es_selected, p_mi );
-    var_AddCallback( p_input_thread, "audio-es", input_es_selected, p_mi );
-    var_AddCallback( p_input_thread, "spu-es", input_es_selected, p_mi );
 }
 
 static void del_es_callbacks( input_thread_t *p_input_thread, libvlc_media_player_t *p_mi )
@@ -926,9 +932,6 @@ static void del_es_callbacks( input_thread_t *p_input_thread, libvlc_media_playe
     var_DelListCallback( p_input_thread, "video-es", input_es_changed, p_mi );
     var_DelListCallback( p_input_thread, "audio-es", input_es_changed, p_mi );
     var_DelListCallback( p_input_thread, "spu-es", input_es_changed, p_mi );
-    var_DelCallback( p_input_thread, "video-es", input_es_selected, p_mi );
-    var_DelCallback( p_input_thread, "audio-es", input_es_selected, p_mi );
-    var_DelCallback( p_input_thread, "spu-es", input_es_selected, p_mi );
 }
 
 /**************************************************************************
@@ -958,6 +961,8 @@ int libvlc_media_player_play( libvlc_media_player_t *p_mi )
         return -1;
     }
 
+    memset( p_mi->selected_es, -2, sizeof(p_mi->selected_es) );
+
     media_attach_preparsed_event( p_mi->p_md );
 
     p_input_thread = input_Create( p_mi, p_mi->p_md->p_input_item, NULL,
diff --git a/lib/media_player_internal.h b/lib/media_player_internal.h
index 1eca3c3f76..a5fa20dc0a 100644
--- a/lib/media_player_internal.h
+++ b/lib/media_player_internal.h
@@ -55,6 +55,7 @@ struct libvlc_media_player_t
     libvlc_event_manager_t * p_event_manager;
     libvlc_state_t state;
     vlc_viewpoint_t viewpoint;
+    int selected_es[3];
 };
 
 /* Media player - audio, video */
-- 
2.11.0



More information about the vlc-devel mailing list