[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