[vlc-devel] [PATCH 01/16] Add vlc_player_SelectTrackList
Roland Bewick
roland.bewick at gmail.com
Tue May 21 20:08:25 CEST 2019
---
include/vlc_es_out.h | 1 +
include/vlc_player.h | 26 ++++++++
modules/access/bluray.c | 1 +
modules/demux/adaptive/plumbing/FakeESOut.cpp | 1 +
src/input/es_out.c | 44 ++++++++++++++
src/input/es_out_timeshift.c | 1 +
src/input/input.c | 22 +++++++
src/input/input_internal.h | 5 ++
src/input/player.c | 85 +++++++++++++++++++++++++++
src/libvlccore.sym | 1 +
10 files changed, 187 insertions(+)
diff --git a/include/vlc_es_out.h b/include/vlc_es_out.h
index b690d570e9..47e2012ab9 100644
--- a/include/vlc_es_out.h
+++ b/include/vlc_es_out.h
@@ -36,6 +36,7 @@ enum es_out_query_e
{
/* set or change the selected ES in its category (audio/video/spu) */
ES_OUT_SET_ES, /* arg1= es_out_id_t* */
+ ES_OUT_SET_ES_LIST, /* arg1= es_out_id_t** */
ES_OUT_UNSET_ES, /* arg1= es_out_id_t* res=can fail */
ES_OUT_RESTART_ES, /* arg1= es_out_id_t* */
diff --git a/include/vlc_player.h b/include/vlc_player.h
index 1aa5f8e687..f2df800797 100644
--- a/include/vlc_player.h
+++ b/include/vlc_player.h
@@ -1675,6 +1675,32 @@ vlc_player_GetSelectedTrack(vlc_player_t *player, enum es_format_category_e cat)
VLC_API void
vlc_player_SelectTrack(vlc_player_t *player, vlc_es_id_t *es_id);
+
+/**
+ * Select multiple tracks from a list of ES identifiers. Any currently
+ * selected track not referenced in the list will be unselected.
+ *
+ * @warning there is no guarantee all requested tracks will be selected.
+ * Only one audio track can be selected at a time. Two subtitle tracks
+ * can be selected simultaneously if dual subtitles are enabled.
+ *
+ * @warning behaviour is undefined if the list is not null-terminated.
+ *
+ * @note A successful call will trigger the
+ * vlc_player_cbs.on_track_selection_changed event for each track that has
+ * its selection state changed.
+ *
+ * @param player locked player instance
+ * @param cat VIDEO_ES, AUDIO_ES or SPU_ES
+ * @param es_id_list a null-terminated list of ES identifiers.
+ * (ES IDs can be retrieved from vlc_player_cbs.on_track_list_changed or
+ * vlc_player_GetTrackAt())
+ */
+VLC_API void
+vlc_player_SelectTrackList(vlc_player_t *player,
+ enum es_format_category_e cat,
+ vlc_es_id_t *const es_id_list[]);
+
/**
* Select the next track
*
diff --git a/modules/access/bluray.c b/modules/access/bluray.c
index c452327aeb..cd88dcc4cf 100644
--- a/modules/access/bluray.c
+++ b/modules/access/bluray.c
@@ -1546,6 +1546,7 @@ static int bluray_esOutControl(es_out_t *p_out, int i_query, va_list args)
case ES_OUT_SET_ES_DEFAULT:
case ES_OUT_SET_ES:
+ case ES_OUT_SET_ES_LIST:
case ES_OUT_UNSET_ES:
case ES_OUT_SET_ES_STATE:
i_ret = VLC_EGENERIC;
diff --git a/modules/demux/adaptive/plumbing/FakeESOut.cpp b/modules/demux/adaptive/plumbing/FakeESOut.cpp
index 69d00f7e7f..f1f274e0cf 100644
--- a/modules/demux/adaptive/plumbing/FakeESOut.cpp
+++ b/modules/demux/adaptive/plumbing/FakeESOut.cpp
@@ -470,6 +470,7 @@ int FakeESOut::esOutControl_Callback(es_out_t *fakees, int i_query, va_list args
}
case ES_OUT_SET_ES:
+ case ES_OUT_SET_ES_LIST:
case ES_OUT_SET_ES_DEFAULT:
case ES_OUT_SET_ES_STATE:
return VLC_SUCCESS;
diff --git a/src/input/es_out.c b/src/input/es_out.c
index 2026fb8c22..933249c39b 100644
--- a/src/input/es_out.c
+++ b/src/input/es_out.c
@@ -217,6 +217,8 @@ static void EsOutDel ( es_out_t *, es_out_id_t * );
static void EsOutTerminate( es_out_t * );
static void EsOutSelect( es_out_t *, es_out_id_t *es, bool b_force );
+static void EsOutSelectList( es_out_t *, enum es_format_category_e cat,
+ vlc_es_id_t **es_id_list );
static void EsOutUpdateInfo( es_out_t *, es_out_id_t *es, const vlc_meta_t * );
static int EsOutSetRecord( es_out_t *, bool b_record );
@@ -2182,6 +2184,41 @@ static void EsOutSelect( es_out_t *out, es_out_id_t *es, bool b_force )
p_esprops->p_main_es = es;
}
+static void EsOutSelectList( es_out_t *out, enum es_format_category_e cat,
+ vlc_es_id_t **es_id_list )
+{
+
+ es_out_sys_t *p_sys = container_of(out, es_out_sys_t, out);
+ es_out_id_t *other;
+
+ foreach_es_then_es_slaves(other)
+ {
+ if( other->fmt.i_cat == cat )
+ {
+ bool select = false;
+ for( size_t i = 0; ; i++ )
+ {
+ vlc_es_id_t *es_id = es_id_list[i];
+ if( es_id == NULL )
+ break;
+ else if( es_id->i_id == other->id.i_id )
+ {
+ select = true;
+ break;
+ }
+ }
+ if( !select && EsIsSelected( other ) )
+ {
+ EsOutUnselectEs( out, other, other->p_pgrm == p_sys->p_pgrm );
+ }
+ else if( select && !EsIsSelected( other ) )
+ {
+ EsOutSelectEs( out, other );
+ }
+ }
+ }
+}
+
static void EsOutCreateCCChannels( es_out_t *out, vlc_fourcc_t codec, uint64_t i_bitmap,
const char *psz_descfmt, es_out_id_t *parent )
{
@@ -2601,6 +2638,13 @@ static int EsOutVaControlLocked( es_out_t *out, int i_query, va_list args )
EsOutStopFreeVout( out );
return VLC_SUCCESS;
}
+ case ES_OUT_SET_ES_LIST:
+ {
+ enum es_format_category_e cat = va_arg( args, enum es_format_category_e );
+ vlc_es_id_t **es_id_list = va_arg( args, vlc_es_id_t ** );
+ EsOutSelectList( out, cat, es_id_list );
+ return VLC_SUCCESS;
+ }
case ES_OUT_UNSET_ES:
{
es_out_id_t *es = va_arg( args, es_out_id_t * ), *other;
diff --git a/src/input/es_out_timeshift.c b/src/input/es_out_timeshift.c
index 406c6f2237..21a041a1f8 100644
--- a/src/input/es_out_timeshift.c
+++ b/src/input/es_out_timeshift.c
@@ -738,6 +738,7 @@ static int ControlLocked( es_out_t *p_out, int i_query, va_list args )
/* Invalid queries for this es_out level */
case ES_OUT_SET_ES_BY_ID:
+ case ES_OUT_SET_ES_LIST:
case ES_OUT_RESTART_ES_BY_ID:
case ES_OUT_SET_ES_DEFAULT_BY_ID:
case ES_OUT_GET_ES_OBJECTS_BY_ID:
diff --git a/src/input/input.c b/src/input/input.c
index 381b85a9fd..eea40b59c1 100644
--- a/src/input/input.c
+++ b/src/input/input.c
@@ -1712,6 +1712,18 @@ static void ControlRelease( int i_type, const input_control_param_t *p_param )
case INPUT_CONTROL_RESTART_ES:
vlc_es_id_Release( p_param->id );
break;
+ case INPUT_CONTROL_SET_ES_LIST:
+ {
+ for( size_t i = 0; ; i++ )
+ {
+ vlc_es_id_t *es_id = p_param->list.ids[i];
+ if( es_id == NULL )
+ break;
+ vlc_es_id_Release( es_id );
+ }
+ free( p_param->list.ids );
+ break;
+ }
default:
break;
@@ -2130,6 +2142,16 @@ static bool Control( input_thread_t *p_input,
demux_Control( input_priv(p_input)->master->p_demux, DEMUX_SET_ES,
vlc_es_id_GetInputId( param.id ) );
break;
+ case INPUT_CONTROL_SET_ES_LIST:
+ {
+ if( es_out_Control( input_priv(p_input)->p_es_out_display,
+ ES_OUT_SET_ES_LIST, param.list.cat,
+ param.list.ids ) == VLC_SUCCESS )
+ {
+ /* TODO: demux_Control(..., DEMUX_SET_ES_LIST, ... ) */
+ }
+ break;
+ }
case INPUT_CONTROL_UNSET_ES:
es_out_Control( input_priv(p_input)->p_es_out_display,
ES_OUT_UNSET_ES, param.id );
diff --git a/src/input/input_internal.h b/src/input/input_internal.h
index 18495881c2..3bcb5a9f83 100644
--- a/src/input/input_internal.h
+++ b/src/input/input_internal.h
@@ -85,6 +85,10 @@ typedef union
vlc_viewpoint_t viewpoint;
vlc_es_id_t *id;
struct {
+ enum es_format_category_e cat;
+ vlc_es_id_t **ids;
+ } list;
+ struct {
bool b_fast_seek;
vlc_tick_t i_val;
} time;
@@ -247,6 +251,7 @@ enum input_control_e
INPUT_CONTROL_RESTART_ES_BY_ID,
INPUT_CONTROL_SET_ES,
+ INPUT_CONTROL_SET_ES_LIST, // select a list of ES atomically
INPUT_CONTROL_UNSET_ES,
INPUT_CONTROL_RESTART_ES,
diff --git a/src/input/player.c b/src/input/player.c
index da02375a66..551b9928f1 100644
--- a/src/input/player.c
+++ b/src/input/player.c
@@ -1312,6 +1312,91 @@ vlc_player_SelectTrack(vlc_player_t *player, vlc_es_id_t *id)
vlc_player_vout_OSDTrack(player, id, true);
}
+void
+vlc_player_SelectTrackList(vlc_player_t *player,
+ enum es_format_category_e cat,
+ vlc_es_id_t *const es_id_list[])
+{
+ struct vlc_player_input *input = vlc_player_get_input_locked(player);
+ if (!input)
+ return;
+
+ /* First, count and hold all the ES Ids.
+ Ids will be released in input.c:ControlRelease */
+ size_t id_count;
+ for (id_count = 0; ; id_count++)
+ {
+ vlc_es_id_t *es_id = es_id_list[id_count];
+ if (es_id == NULL)
+ break;
+
+ vlc_es_id_Hold( es_id );
+ }
+
+ /* Copy es_id_list into an allocated list so that it remains in memory until
+ selection completes. The list will be freed in input.c:ControlRelease */
+ struct vlc_es_id_t **allocated_ids =
+ malloc(sizeof(vlc_es_id_t *) * (id_count + 1));
+
+ for (size_t i = 0; i <= id_count; i++)
+ {
+ allocated_ids[i] = es_id_list[i];
+ }
+
+ /* Attempt to select all the requested tracks */
+ input_ControlPush( input->thread, INPUT_CONTROL_SET_ES_LIST,
+ &(input_control_param_t) {
+ .list.cat = cat,
+ .list.ids = allocated_ids,
+ } );
+
+ /* Display track selection message */
+ bool selected_new_track = false;
+ for (size_t i = 0; i < id_count; i++)
+ {
+ vlc_es_id_t *es_id = es_id_list[i];
+
+ const struct vlc_player_track *track = vlc_player_GetTrack(player, es_id);
+ assert(track);
+
+ if (!track->selected)
+ {
+ vlc_player_vout_OSDTrack(player, es_id, true);
+ selected_new_track = true;
+ }
+ }
+
+ if (!selected_new_track)
+ {
+ /* Display track deselection message */
+ size_t count = vlc_player_GetTrackCount(player, cat);
+ if (!count)
+ return;
+
+ for (size_t i = 0; i < count; ++i)
+ {
+ const struct vlc_player_track *track =
+ vlc_player_GetTrackAt(player, cat, i);
+ assert(track);
+ if (track->selected)
+ {
+ bool selected = false;
+ for (size_t j = 0; j < id_count; j++)
+ {
+ if (es_id_list[j] == track->es_id)
+ {
+ selected = true;
+ break;
+ }
+ }
+
+ if (!selected)
+ vlc_player_vout_OSDTrack(player, track->es_id, false);
+ }
+ }
+ }
+}
+
static void
vlc_player_CycleTrack(vlc_player_t *player, enum es_format_category_e cat,
bool next)
diff --git a/src/libvlccore.sym b/src/libvlccore.sym
index efc07fbb25..03a503e1ea 100644
--- a/src/libvlccore.sym
+++ b/src/libvlccore.sym
@@ -856,6 +856,7 @@ vlc_player_SelectTeletextPage
vlc_player_SelectTitle
vlc_player_SelectTitleIdx
vlc_player_SelectTrack
+vlc_player_SelectTrackList
vlc_player_SetAssociatedSubsFPS
vlc_player_SetAtoBLoop
vlc_player_SetAudioDelay
--
2.11.0
More information about the vlc-devel
mailing list