From 2e462c506231d1e8e449f1d75dc615d79215f6b2 Mon Sep 17 00:00:00 2001 From: Vikram Kangotra Date: Wed, 29 May 2024 01:38:49 +0530 Subject: [PATCH] extensions_manager: Introduce typed callbacks for extensions_manager This commit introduces a typed virtual table for operations on extensions_manager, aiming at replacing the legacy pf_control() callback which is using va_list. The operations can now be implemented directly by the modules, providing type safety at every level. When no operation is provided (i.e., extensions_manager_t.ops is NULL) by a module implementation, the legacy pf_control will be used instead as a fallback. --- include/vlc_extensions.h | 34 +++++++++++- src/Makefile.am | 1 + src/libvlccore.sym | 1 + src/meson.build | 1 + src/misc/extensions.c | 113 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 148 insertions(+), 2 deletions(-) create mode 100644 src/misc/extensions.c diff --git a/include/vlc_extensions.h b/include/vlc_extensions.h index 940f4314ef..46401d4ea6 100644 --- a/include/vlc_extensions.h +++ b/include/vlc_extensions.h @@ -55,6 +55,20 @@ typedef struct extension_t { int i_icondata_size; /**< Size of that data */ } extension_t; +struct vlc_extensions_manager_operations { + int (*activate)(extensions_manager_t*, extension_t *); + int (*deactivate)(extensions_manager_t *, extension_t *); + bool (*is_activated)(extensions_manager_t *, extension_t *); + bool (*has_menu)(extensions_manager_t *, extension_t *); + int (*get_menu)(extensions_manager_t *, extension_t *, char ***, uint16_t **); + bool (*trigger_only)(extensions_manager_t *, extension_t *); + int (*trigger)(extensions_manager_t *, extension_t *); + int (*trigger_menu)(extensions_manager_t *, extension_t *, int); + int (*set_input)(extensions_manager_t *, extension_t *, input_item_t *); + int (*playing_changed)(extensions_manager_t *, extension_t *, int); + int (*meta_changed)(extensions_manager_t *, extension_t *); +}; + /** Extensions manager object */ struct extensions_manager_t { @@ -67,8 +81,19 @@ struct extensions_manager_t DECL_ARRAY(extension_t*) extensions; /**< Array of extension descriptors */ vlc_mutex_t lock; /**< A lock for the extensions array */ - /** Control, see extension_Control */ + /** Control, see extension_Control + * + * Legacy way of implementing callbacks. + * \ref vlc_extensions_manager_operations should be preferred. + */ int (*pf_control)(extensions_manager_t*, int, extension_t *, va_list); + + /** + * Implementation of the extension manager operations. + * + * If NULL all operations will be redirected to \ref extensions_manager_t.pf_control + */ + const struct vlc_extensions_manager_operations *ops; }; /* Control commands */ @@ -88,6 +113,11 @@ enum EXTENSION_META_CHANGED, /**< arg1: extension_t*, arg2 (input_item_t*) */ }; +VLC_API int vlc_extension_VaControl( extensions_manager_t *p_mgr, + int i_control, + extension_t *ext, + va_list args ); + /** * Control function for extensions. * Every GUI -> extension command will go through this function. @@ -98,7 +128,7 @@ static inline int extension_Control( extensions_manager_t *p_mgr, { va_list args; va_start(args, ext); - int i_ret = p_mgr->pf_control(p_mgr, i_control, ext, args); + int i_ret = vlc_extension_VaControl(p_mgr, i_control, ext, args); va_end( args ); return i_ret; } diff --git a/src/Makefile.am b/src/Makefile.am index a853a2897f..3701c07b1f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -392,6 +392,7 @@ libvlccore_la_SOURCES = \ misc/fourcc.c \ misc/fourcc_list.h \ misc/es_format.c \ + misc/extensions.c \ misc/picture.c \ misc/picture.h \ misc/picture_fifo.c \ diff --git a/src/libvlccore.sym b/src/libvlccore.sym index 81255e7930..ba18a367ab 100644 --- a/src/libvlccore.sym +++ b/src/libvlccore.sym @@ -113,6 +113,7 @@ es_format_Init es_format_InitFromVideo es_format_IsSimilar es_format_LogDifferences +vlc_extension_VaControl filter_AddProxyCallbacks filter_DelProxyCallbacks filter_Blend diff --git a/src/meson.build b/src/meson.build index 79484a6bdf..0486739a21 100644 --- a/src/meson.build +++ b/src/meson.build @@ -243,6 +243,7 @@ libvlccore_sources_base = files( 'misc/fourcc.c', 'misc/fourcc_list.h', 'misc/es_format.c', + 'misc/extensions.c', 'misc/picture.c', 'misc/picture.h', 'misc/picture_fifo.c', diff --git a/src/misc/extensions.c b/src/misc/extensions.c new file mode 100644 index 0000000000..d1b7f177e2 --- /dev/null +++ b/src/misc/extensions.c @@ -0,0 +1,113 @@ +/***************************************************************************** + * extensions.c + ***************************************************************************** + * Copyright (C) 2024 VideoLabs + * + * Authors: Vikram Kangotra + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + *****************************************************************************/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include +#include + +int vlc_extension_VaControl( extensions_manager_t *p_mgr, + int i_control, + extension_t *ext, + va_list args ) +{ + if (p_mgr->ops == NULL) + return p_mgr->pf_control(p_mgr, i_control, ext, args); + + switch (i_control) { + case EXTENSION_ACTIVATE: + if (p_mgr->ops->activate != NULL) + return p_mgr->ops->activate(p_mgr, ext); + return VLC_EGENERIC; + case EXTENSION_DEACTIVATE: + if (p_mgr->ops->deactivate != NULL) + return p_mgr->ops->deactivate(p_mgr, ext); + return VLC_EGENERIC; + case EXTENSION_IS_ACTIVATED: + { + bool *is_activated = va_arg(args, bool *); + if (p_mgr->ops->is_activated != NULL) + *is_activated = p_mgr->ops->is_activated(p_mgr, ext); + else + *is_activated = false; + return VLC_SUCCESS; + } + case EXTENSION_HAS_MENU: + { + bool *has_menu = va_arg(args, bool *); + if (p_mgr->ops->has_menu != NULL) + *has_menu = p_mgr->ops->has_menu(p_mgr, ext); + else + *has_menu = false; + return VLC_SUCCESS; + } + case EXTENSION_GET_MENU: + if (p_mgr->ops->get_menu != NULL) { + char ***pppsz_titles = va_arg(args, char ***); + uint16_t **ppi_ids = va_arg(args, uint16_t **); + return p_mgr->ops->get_menu(p_mgr, ext, pppsz_titles, ppi_ids); + } + return VLC_EGENERIC; + case EXTENSION_TRIGGER_ONLY: + { + bool *p_trigger_only = va_arg(args, bool *); + if (p_mgr->ops->trigger_only != NULL) + *p_trigger_only = p_mgr->ops->trigger_only(p_mgr, ext); + else + *p_trigger_only = false; + return VLC_SUCCESS; + } + case EXTENSION_TRIGGER: + if (p_mgr->ops->trigger != NULL) + return p_mgr->ops->trigger(p_mgr, ext); + return VLC_EGENERIC; + case EXTENSION_TRIGGER_MENU: + if (p_mgr->ops->trigger_menu != NULL) { + int i = va_arg(args, int); + return p_mgr->ops->trigger_menu(p_mgr, ext, i); + } + return VLC_EGENERIC; + case EXTENSION_SET_INPUT: + if (p_mgr->ops->set_input != NULL) { + input_item_t *p_item = va_arg(args, input_item_t *); + return p_mgr->ops->set_input(p_mgr, ext, p_item); + } + return VLC_EGENERIC; + case EXTENSION_PLAYING_CHANGED: + if (p_mgr->ops->playing_changed != NULL) { + int i = va_arg(args, int); + return p_mgr->ops->playing_changed(p_mgr, ext, i); + } + return VLC_EGENERIC; + case EXTENSION_META_CHANGED: + if (p_mgr->ops->meta_changed != NULL) + return p_mgr->ops->meta_changed(p_mgr, ext); + return VLC_EGENERIC; + default: + vlc_assert_unreachable(); + } +} +