[vlc-devel] [PATCH 3/4] es_out: add controls to cycle through programs

Thomas Guillem thomas at gllm.fr
Wed Nov 14 17:50:17 CET 2018


With 2 new internal controls: ES_OUT_SET_GROUP_NEXT, and ES_OUT_SET_GROUP_PREV.
This will fix a TOCTOU issue when selecting next or previous programs.
---
 src/input/es_out.c           | 55 ++++++++++++++++++++++++++++++++++++
 src/input/es_out.h           |  3 ++
 src/input/es_out_timeshift.c |  2 ++
 3 files changed, 60 insertions(+)

diff --git a/src/input/es_out.c b/src/input/es_out.c
index 2960374175..893bde7630 100644
--- a/src/input/es_out.c
+++ b/src/input/es_out.c
@@ -2461,6 +2461,53 @@ static int EsOutControlCycleEsLocked(es_out_t *out, enum es_format_category_e ca
     }
 }
 
+static int EsOutControlCycleGroupLocked(es_out_t *out, bool next, int *new_id)
+{
+    es_out_sys_t *p_sys = container_of(out, es_out_sys_t, out);
+    es_out_pgrm_t *pgrm;
+    es_out_pgrm_t *new_pgrm = NULL;
+
+    if (next)
+    {
+        vlc_list_foreach(pgrm, &p_sys->programs, node)
+        {
+            if (pgrm == p_sys->p_pgrm)
+            {
+                new_pgrm = vlc_list_next_entry_or_null(&p_sys->programs, pgrm,
+                                                        es_out_pgrm_t, node);
+                if (new_pgrm == NULL)
+                    new_pgrm = vlc_list_first_entry_or_null(&p_sys->programs,
+                                                            es_out_pgrm_t, node);
+                break;
+            }
+        }
+    }
+    else
+    {
+        vlc_list_foreach(pgrm, &p_sys->programs, node)
+        {
+            es_out_pgrm_t *next_pgrm =
+                vlc_list_next_entry_or_null(&p_sys->programs, pgrm,
+                                            es_out_pgrm_t, node);
+            if (next_pgrm == p_sys->p_pgrm)
+            {
+                new_pgrm = pgrm;
+                break;
+            }
+        }
+        if (new_pgrm == NULL)
+            new_pgrm = vlc_list_last_entry_or_null(&p_sys->programs,
+                                                   es_out_pgrm_t, node);
+    }
+    if (new_pgrm && new_pgrm != p_sys->p_pgrm)
+    {
+        EsOutProgramSelect(out, new_pgrm);
+        *new_id = new_pgrm->i_id;
+        return VLC_SUCCESS;
+    }
+    return VLC_EGENERIC;
+}
+
 /**
  * Control query handler
  *
@@ -2840,6 +2887,14 @@ static int EsOutVaControlLocked( es_out_t *out, int i_query, va_list args )
             }
         return VLC_EGENERIC;
     }
+    case ES_OUT_SET_GROUP_NEXT:
+    case ES_OUT_SET_GROUP_PREV:
+    {
+        int *new_id = va_arg(args, int *);
+        return EsOutControlCycleGroupLocked(out,
+                                            i_query == ES_OUT_SET_GROUP_NEXT,
+                                            new_id);
+    }
 
     case ES_OUT_SET_ES_FMT:
     {
diff --git a/src/input/es_out.h b/src/input/es_out.h
index 5f216905bd..8964839610 100644
--- a/src/input/es_out.h
+++ b/src/input/es_out.h
@@ -53,6 +53,9 @@ enum es_out_query_private_e
     ES_OUT_SET_ES_NEXT, /* arg1=es_category_e, arg2= vlc_es_id_t **, res=can fail */
     ES_OUT_SET_ES_PREV, /* arg1=es_category_e, arg2= vlc_es_id_t **, res=can fail */
 
+    ES_OUT_SET_GROUP_NEXT, /* arg1=int *, res= can fail */
+    ES_OUT_SET_GROUP_PREV, /* arg1=int *, res= can fail */
+
     /* Stop all selected ES and save the stopped state in a context. free the
      * context or call ES_OUT_STOP_ALL_ES */
     ES_OUT_STOP_ALL_ES,                             /* arg1=void ** */
diff --git a/src/input/es_out_timeshift.c b/src/input/es_out_timeshift.c
index 5e7ffcd8e6..9a565e77bc 100644
--- a/src/input/es_out_timeshift.c
+++ b/src/input/es_out_timeshift.c
@@ -742,6 +742,8 @@ static int ControlLocked( es_out_t *p_out, int i_query, va_list args )
     case ES_OUT_SET_ES_BY_ID:
     case ES_OUT_SET_ES_NEXT:
     case ES_OUT_SET_ES_PREV:
+    case ES_OUT_SET_GROUP_NEXT:
+    case ES_OUT_SET_GROUP_PREV:
     case ES_OUT_RESTART_ES_BY_ID:
     case ES_OUT_SET_ES_DEFAULT_BY_ID:
     case ES_OUT_GET_ES_OBJECTS_BY_ID:
-- 
2.19.1



More information about the vlc-devel mailing list