[vlc-devel] [PATCH] libvlc: add dialog API
Thomas Guillem
thomas at gllm.fr
Wed Feb 3 18:01:55 CET 2016
On Wed, Feb 3, 2016, at 17:56, Rémi Denis-Courmont wrote:
> 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.
Maybe... and it's what I did for android: one callback per dialog type.
>
> > + /**
> > + * 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/
>
> _______________________________________________
> vlc-devel mailing list
> To unsubscribe or modify your subscription options:
> https://mailman.videolan.org/listinfo/vlc-devel
More information about the vlc-devel
mailing list