[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