[vlc-devel] [PATCH] libvlc: add dialog API
Rémi Denis-Courmont
remi at remlab.net
Wed Feb 3 17:56:24 CET 2016
On Monday 01 February 2016 19:02:42 Thomas Guillem wrote:
> ---
> include/vlc/libvlc_dialog.h | 223
> ++++++++++++++++++++++++++++++++++++++++++++ lib/Makefile.am |
> 2 +
> lib/dialog.c | 161 ++++++++++++++++++++++++++++++++
> lib/libvlc.sym | 6 ++
> lib/libvlc_internal.h | 6 ++
> 5 files changed, 398 insertions(+)
> create mode 100644 include/vlc/libvlc_dialog.h
> create mode 100644 lib/dialog.c
>
> diff --git a/include/vlc/libvlc_dialog.h b/include/vlc/libvlc_dialog.h
> new file mode 100644
> index 0000000..589f1f1
> --- /dev/null
> +++ b/include/vlc/libvlc_dialog.h
> @@ -0,0 +1,223 @@
> +/**************************************************************************
> *** + * libvlc_dialog.h: libvlc dialog API
> +
> ***************************************************************************
> ** + * Copyright © 2016 VLC authors and VideoLAN
> + *
> + * 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. +
> ***************************************************************************
> **/ +
> +#ifndef LIBVLC_DIALOG_H
> +#define LIBVLC_DIALOG_H 1
> +
> +#include <stdbool.h>
> +
> +# ifdef __cplusplus
> +extern "C" {
> +# endif
> +
> +typedef struct libvlc_dialog_id libvlc_dialog_id;
> +
> +/**
> + * @defgroup libvlc_dialog LibVLC dialog
> + * @ingroup libvlc
> + * @{
> + * @file
> + * LibVLC dialog external API
> + */
> +
> +typedef enum libvlc_dialog_question_type
> +{
> + LIBVLC_DIALOG_QUESTION_NORMAL,
> + LIBVLC_DIALOG_QUESTION_WARNING,
> + LIBVLC_DIALOG_QUESTION_CRITICAL,
> +} libvlc_dialog_question_type;
> +
> +typedef enum libvlc_dialog_type
> +{
> + LIBVLC_DIALOG_ERROR,
> + LIBVLC_DIALOG_LOGIN,
> + LIBVLC_DIALOG_QUESTION,
> + LIBVLC_DIALOG_PROGRESS,
> +} libvlc_dialog_type;
> +
> +/** Dialog to be displayed */
> +typedef struct libvlc_dialog
> +{
> + libvlc_dialog_type i_type;
> + /** title of the dialog */
> + const char *psz_title;
> + /** text of the dialog */
> + const char *psz_text;
> +
> + union
> + {
> + /** if i_type == LIBVLC_DIALOG_LOGIN */
> + struct
> + {
> + /** default user name that should be set on the user form */
> + const char *psz_default_username;
> + /** if true, ask the user if he wants to save the credentials
> */ + bool b_ask_store;
> + } login;
> + /** if i_type == LIBVLC_DIALOG_QUESTION */
> + struct
> + {
> + /** question type (or severity) of the dialog */
> + libvlc_dialog_question_type i_type;
> + /** text of the cancel button */
> + const char *psz_cancel;
> + /** text of the first button (optional) */
> + const char *psz_action1;
> + /** text of the second button (optional) */
> + const char *psz_action2;
> + } question;
> + /** if i_type == LIBVLC_DIALOG_PROGRESS */
> + struct
> + {
> + /** true if the progress dialog is indeterminate */
> + bool b_indeterminate;
> + /** initial position of the progress bar (between 0.0 and 1.0)
> */ + float f_position;
> + /** text of the cancel button, if NULL the dialog is not
> + * cancellable (optional) */
> + const char *psz_cancel;
> + } progress;
> + } u;
> +} libvlc_dialog;
> +
> +/**
> + * Dialog callbacks to be implemented
> + *
> + * pf_display and pf_cancel are mandatory.
> + */
> +typedef struct libvlc_dialog_cbs
> +{
> + /**
> + * Called when a new dialog needs to be displayed
> + *
> + * You can interact with the dialog by calling
> libvlc_dialog_post_login()
> + * for LIBVLC_DIALOG_LOGIN type,
> libvlc_dialog_post_action() for
> + * LIBVLC_DIALOG_QUESTION type or
> libvlc_dialog_dimiss() in order to cancel
> + * the dialog.
> + *
> + * @param p_id id used to interact with the dialog, can be null (for
> the
> + * LIBVLC_DIALOG_ERROR case)
> + * @param p_dialog all informations that need to be displayed
> + * @param p_data opaque pointer for the callback
> + * @return true if the dialog is handled by the callback, false
> otherwise + */
> + bool (*pf_display)(libvlc_dialog_id *p_id, libvlc_dialog *p_dialog,
> + void *p_data);
I´d think that one type-specific callback with type-specific prototype per
dialog type is less error prone, and less likely to explode if new types are
introduced.
> + /**
> + * Called when a displayed dialog needs to be cancelled
> + *
> + * The implementation must call libvlc_dialog_dismiss() to really
> release + * the dialog.
> + *
> + * @param p_id id of the dialog
> + * @param p_data opaque pointer for the callback
> + */
> + void (*pf_cancel)(libvlc_dialog_id *p_id, void *p_data);
> + /**
> + * Called when a progress dialog needs to be updated (optional)
> + *
> + * @param p_id id of the dialog
> + * @param f_position osition of the progress bar (between 0.0 and 1.0)
> + * @param psz_text new text of the progress dialog
> + * @param p_data opaque pointer for the callback
> + */
> + void (*pf_update_progress)(libvlc_dialog_id *p_id, float f_position,
> + const char *psz_text, void *p_data);
> +} libvlc_dialog_cbs;
> +
> +/**
> + * Register callbacks to handle VLC dialogs
> + *
> + * @version LibVLC 3.0.0 and later.
> + *
> + * @param p_cbs a pointer to callbacks, or NULL to unregister callbacks.
> + * @param p_data opaque pointer for the callback
> + */
> +LIBVLC_API void
> +libvlc_dialog_set_callbacks(libvlc_instance_t *p_instance,
> + const libvlc_dialog_cbs *p_cbs, void *p_data);
> +
> +/**
> + * Associate an opaque pointer with the dialog id
> + *
> + * @version LibVLC 3.0.0 and later.
> + */
> +LIBVLC_API void
> +libvlc_dialog_set_context(libvlc_dialog_id *p_id, void *p_context);
> +
> +/**
> + * Return the opaque pointer associated with the dialog id
> + *
> + * @version LibVLC 3.0.0 and later.
> + */
> +LIBVLC_API void *
> +libvlc_dialog_get_context(libvlc_dialog_id *p_id);
> +
> +/**
> + * Post a login answer
> + *
> + * After this call, p_id won't be valid anymore
> + *
> + * @version LibVLC 3.0.0 and later.
> + *
> + * @param p_id id of the dialog
> + * @param psz_username valid and non empty string
> + * @param psz_password valid string (can be empty)
> + * @param b_store if true, store the credentials
> + * @return 0 on success, or -1 on error
> + */
> +LIBVLC_API int
> +libvlc_dialog_post_login(libvlc_dialog_id *p_id, const char *psz_username,
> + const char *psz_password, bool b_store);
> +
> +/**
> + * Post a question answer
> + *
> + * After this call, p_id won't be valid anymore
> + *
> + * @version LibVLC 3.0.0 and later.
> + *
> + * @param p_id id of the dialog
> + * @param i_action 1 for action1, 2 for action2
> + * @return 0 on success, or -1 on error
> + */
> +LIBVLC_API int
> +libvlc_dialog_post_action(libvlc_dialog_id *p_id, int i_action);
> +
> +/**
> + * Dismiss a dialog
> + *
> + * After this call, p_id won't be valid anymore
> + *
> + * @version LibVLC 3.0.0 and later.
> + *
> + * @param p_id id of the dialog
> + * @return 0 on success, or -1 on error
> + */
> +LIBVLC_API int
> +libvlc_dialog_dismiss(libvlc_dialog_id *p_id);
> +
> +/** @} */
> +
> +# ifdef __cplusplus
> +}
> +# endif
> +
> +#endif /* LIBVLC_DIALOG_H */
> diff --git a/lib/Makefile.am b/lib/Makefile.am
> index a32260d..a4f87d0 100644
> --- a/lib/Makefile.am
> +++ b/lib/Makefile.am
> @@ -11,6 +11,7 @@ CLEANFILES = $(BUILT_SOURCES) $(pkgconfig_DATA)
> pkginclude_HEADERS = \
> ../include/vlc/deprecated.h \
> ../include/vlc/libvlc.h \
> + ../include/vlc/libvlc_dialog.h \
> ../include/vlc/libvlc_events.h \
> ../include/vlc/libvlc_media.h \
> ../include/vlc/libvlc_media_discoverer.h \
> @@ -36,6 +37,7 @@ libvlc_la_SOURCES = \
> media_list_internal.h \
> media_player_internal.h \
> core.c \
> + dialog.c \
> error.c \
> log.c \
> playlist.c \
> diff --git a/lib/dialog.c b/lib/dialog.c
> new file mode 100644
> index 0000000..62b6f3a
> --- /dev/null
> +++ b/lib/dialog.c
> @@ -0,0 +1,161 @@
> +/**************************************************************************
> *** + * dialog.c: libvlc dialog API
> +
> ***************************************************************************
> ** + * Copyright © 2016 VLC authors and VideoLAN
> + *
> + * 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 <assert.h>
> +
> +#include <vlc/libvlc.h>
> +#include <vlc/libvlc_dialog.h>
> +
> +#include <vlc_common.h>
> +#include <vlc_dialog.h>
> +
> +#include "libvlc_internal.h"
> +
> +static libvlc_dialog_question_type
> +vlc_to_libvlc_dialog_question_type(vlc_dialog_question_type i_type)
> +{
> + switch (i_type)
> + {
> + case VLC_DIALOG_QUESTION_NORMAL: return LIBVLC_DIALOG_QUESTION_NORMAL;
> + case VLC_DIALOG_QUESTION_WARNING: return
> LIBVLC_DIALOG_QUESTION_WARNING; + case VLC_DIALOG_QUESTION_CRITICAL:
> return LIBVLC_DIALOG_QUESTION_CRITICAL; + default:
> vlc_assert_unreachable();
> + }
> +}
> +
> +static bool
> +display_cb(vlc_dialog_id *p_id, vlc_dialog *p_dialog, void *p_data)
> +{
> + libvlc_instance_t *p_instance = p_data;
> +
> + libvlc_dialog ldialog;
> + ldialog.psz_title = p_dialog->psz_title;
> + ldialog.psz_text = p_dialog->psz_text;
> + switch (p_dialog->i_type)
> + {
> + case VLC_DIALOG_ERROR:
> + ldialog.i_type = LIBVLC_DIALOG_ERROR;
> + break;
> + case VLC_DIALOG_LOGIN:
> + ldialog.i_type = LIBVLC_DIALOG_LOGIN;
> + ldialog.u.login.psz_default_username =
> + p_dialog->u.login.psz_default_username;
> + ldialog.u.login.b_ask_store = p_dialog->u.login.b_ask_store;
> + break;
> + case VLC_DIALOG_QUESTION:
> + ldialog.i_type = LIBVLC_DIALOG_QUESTION;
> + ldialog.u.question.i_type =
> +
> vlc_to_libvlc_dialog_question_type(p_dialog->u.question.i_type); +
> ldialog.u.question.psz_cancel = p_dialog->u.question.psz_cancel; +
> ldialog.u.question.psz_action1 = p_dialog->u.question.psz_action1; +
> ldialog.u.question.psz_action2 = p_dialog->u.question.psz_action2; +
> break;
> + case VLC_DIALOG_PROGRESS:
> + ldialog.i_type = LIBVLC_DIALOG_PROGRESS;
> + ldialog.u.progress.b_indeterminate =
> + p_dialog->u.progress.b_indeterminate;
> + ldialog.u.progress.f_position = p_dialog->u.progress.f_position;
> + ldialog.u.progress.psz_cancel = p_dialog->u.progress.psz_cancel;
> + break;
> + default:
> + vlc_assert_unreachable();
> + }
> + return p_instance->dialog.cbs.pf_display((libvlc_dialog_id *)p_id,
> + &ldialog,
> + p_instance->dialog.data);
> +}
> +
> +static void cancel_cb(vlc_dialog_id *p_id, void *p_data)
> +{
> + libvlc_instance_t *p_instance = p_data;
> + p_instance->dialog.cbs.pf_cancel((libvlc_dialog_id *)p_id,
> + p_instance->dialog.data);
> +}
> +
> +static void
> +update_progress_cb(vlc_dialog_id *p_id, float f_position, const char
> *psz_text, + void *p_data)
> +{
> + libvlc_instance_t *p_instance = p_data;
> + p_instance->dialog.cbs.pf_update_progress((libvlc_dialog_id *) p_id,
> + f_position, psz_text,
> + p_instance->dialog.data);
> +}
> +
> +static const vlc_dialog_cbs dialog_cbs = {
> + .pf_display = display_cb,
> + .pf_cancel = cancel_cb,
> + .pf_update_progress = update_progress_cb,
> +};
> +
> +void
> +libvlc_dialog_set_callbacks(libvlc_instance_t *p_instance,
> + const libvlc_dialog_cbs *p_cbs, void *p_data)
> +{
> + libvlc_int_t *p_libvlc = p_instance->p_libvlc_int;
> +
> + vlc_mutex_lock(&p_instance->instance_lock);
> + p_instance->dialog.cbs = *p_cbs;
> + p_instance->dialog.data = p_data;
> + if (p_cbs != NULL)
> + vlc_dialog_provider_set_callbacks(p_libvlc, &dialog_cbs,
> p_instance); + else
> + vlc_dialog_provider_set_callbacks(p_libvlc, NULL, NULL);
> + vlc_mutex_unlock(&p_instance->instance_lock);
> +}
> +
> +void
> +libvlc_dialog_set_context(libvlc_dialog_id *p_id, void *p_context)
> +{
> + vlc_dialog_id_set_context((vlc_dialog_id *)p_id, p_context);
> +}
> +
> +void *
> +libvlc_dialog_get_context(libvlc_dialog_id *p_id)
> +{
> + return vlc_dialog_id_get_context((vlc_dialog_id *)p_id);
> +}
> +
> +int
> +libvlc_dialog_post_login(libvlc_dialog_id *p_id, const char *psz_username,
> + const char *psz_password, bool b_store)
> +{
> + int i_ret = vlc_dialog_id_post_login((vlc_dialog_id *)p_id,
> psz_username, + psz_password,
> b_store);
> + return i_ret == VLC_SUCCESS ? 0 : -1;
> +}
> +
> +int
> +libvlc_dialog_post_action(libvlc_dialog_id *p_id, int i_action)
> +{
> + int i_ret = vlc_dialog_id_post_action((vlc_dialog_id *)p_id, i_action);
> + return i_ret == VLC_SUCCESS ? 0 : -1;
> +}
> +
> +int
> +libvlc_dialog_dismiss(libvlc_dialog_id *p_id)
> +{
> + int i_ret = vlc_dialog_id_dismiss((vlc_dialog_id *)p_id);
> + return i_ret == VLC_SUCCESS ? 0 : -1;
> +}
> diff --git a/lib/libvlc.sym b/lib/libvlc.sym
> index 49207db..3ca9f18 100644
> --- a/lib/libvlc.sym
> +++ b/lib/libvlc.sym
> @@ -46,6 +46,12 @@ libvlc_audio_set_callbacks
> libvlc_audio_set_volume_callback
> libvlc_chapter_descriptions_release
> libvlc_clock
> +libvlc_dialog_dismiss
> +libvlc_dialog_get_context
> +libvlc_dialog_post_action
> +libvlc_dialog_post_login
> +libvlc_dialog_set_callbacks
> +libvlc_dialog_set_context
> libvlc_event_attach
> libvlc_event_detach
> libvlc_event_type_name
> diff --git a/lib/libvlc_internal.h b/lib/libvlc_internal.h
> index b37b749..ac853b6 100644
> --- a/lib/libvlc_internal.h
> +++ b/lib/libvlc_internal.h
> @@ -31,6 +31,7 @@
>
> #include <vlc/libvlc_structures.h>
> #include <vlc/libvlc.h>
> +#include <vlc/libvlc_dialog.h>
> #include <vlc/libvlc_media.h>
> #include <vlc/libvlc_events.h>
>
> @@ -78,6 +79,11 @@ struct libvlc_instance_t
> void (*cb) (void *, int, const libvlc_log_t *, const char *,
> va_list); void *data;
> } log;
> + struct
> + {
> + libvlc_dialog_cbs cbs;
> + void *data;
> + } dialog;
> };
--
Rémi Denis-Courmont
http://www.remlab.net/
More information about the vlc-devel
mailing list