dialogs: split callbacks between interactive and non-interactive callbacks

this allows an application to manage error messages outside of the UI
lifetime. For instance to store error messages before the UI is loaded and able
to handle dialogs.

ref: #26378
This commit is contained in:
Pierre Lamot 2022-04-27 15:49:18 +02:00 committed by Rémi Denis-Courmont
parent 1241d4bf60
commit 211baa3ffe
9 changed files with 105 additions and 36 deletions

View File

@ -46,19 +46,15 @@ typedef enum libvlc_dialog_question_type
/**
* Dialog callbacks to be implemented
*
* @attention starting with vlc 4.0.0 the error callback (pf_display_error) is
* no longer part of this struct and need to be registered separately
* using @a libvlc_dialog_set_error_callback
*
* @see libvlc_dialog_set_error_callback
*/
typedef struct libvlc_dialog_cbs
{
/**
* Called when an error message needs to be displayed
*
* @param p_data opaque pointer for the callback
* @param psz_title title of the dialog
* @param psz_text text of the dialog
*/
void (*pf_display_error)(void *p_data, const char *psz_title,
const char *psz_text);
/**
* Called when a login dialog needs to be displayed
*
@ -154,6 +150,16 @@ typedef struct libvlc_dialog_cbs
float f_position, const char *psz_text);
} libvlc_dialog_cbs;
/**
* Called when an error message needs to be displayed
*
* @param p_data opaque pointer for the callback
* @param psz_title title of the dialog
* @param psz_text text of the dialog
*/
typedef void (*libvlc_dialog_error_cbs)(void *p_data, const char *psz_title, const char *psz_text);
/**
* Register callbacks in order to handle VLC dialogs
*
@ -166,6 +172,18 @@ LIBVLC_API void
libvlc_dialog_set_callbacks(libvlc_instance_t *p_instance,
const libvlc_dialog_cbs *p_cbs, void *p_data);
/*
* Register callback in order to handle VLC error messages
*
* @version LibVLC 4.0.0 and later.
*
* @param p_cbs a pointer to callback, or NULL to unregister callback.
* @param p_data opaque pointer for the callback
*/
LIBVLC_API void
libvlc_dialog_set_error_callback(libvlc_instance_t *p_instance,
libvlc_dialog_error_cbs p_cbs, void *p_data);
/**
* Associate an opaque pointer with the dialog id
*

View File

@ -274,16 +274,6 @@ vlc_dialog_is_cancelled(vlc_object_t *p_obj, vlc_dialog_id *p_id);
*/
typedef struct vlc_dialog_cbs
{
/**
* Called when an error message needs to be displayed
*
* @param p_data opaque pointer for the callback
* @param psz_title title of the dialog
* @param psz_text text of the dialog
*/
void (*pf_display_error)(void *p_data, const char *psz_title,
const char *psz_text);
/**
* Called when a login dialog needs to be displayed
*
@ -379,6 +369,15 @@ typedef struct vlc_dialog_cbs
float f_position, const char *psz_text);
} vlc_dialog_cbs;
/**
* Called when an error message needs to be displayed
*
* @param p_data opaque pointer for the callback
* @param psz_title title of the dialog
* @param psz_text text of the dialog
*/
typedef void (*vlc_dialog_error_cbs)(void *p_data, const char *psz_title, const char *psz_text);
/**
* Register callbacks to handle VLC dialogs
*
@ -391,6 +390,20 @@ vlc_dialog_provider_set_callbacks(vlc_object_t *p_obj,
#define vlc_dialog_provider_set_callbacks(a, b, c) \
vlc_dialog_provider_set_callbacks(VLC_OBJECT(a), b, c)
/**
* Register callbacks to handle VLC error messages
*
* @version LibVLC 4.0.0 and later.
*
* @param p_cbs a pointer to the callback, or NULL to unregister the callback.
* @param p_data opaque pointer for the callback
*/
VLC_API void
vlc_dialog_provider_set_error_callback(vlc_object_t *p_obj,
vlc_dialog_error_cbs p_cbs, void *p_data);
#define vlc_dialog_provider_set_error_callback(a, b, c) \
vlc_dialog_provider_set_error_callback(VLC_OBJECT(a), b, c)
/**
* Associate an opaque pointer with the dialog id
*/

View File

@ -44,15 +44,6 @@ vlc_to_libvlc_dialog_question_type(vlc_dialog_question_type i_type)
}
}
static void
display_error_cb(void *p_data, const char *psz_title, const char *psz_text)
{
libvlc_instance_t *p_instance = p_data;
p_instance->dialog.cbs.pf_display_error(p_instance->dialog.data, psz_title,
psz_text);
}
static void
display_login_cb(void *p_data, vlc_dialog_id *p_id, const char *psz_title,
const char *psz_text, const char *psz_default_username,
@ -124,8 +115,6 @@ libvlc_dialog_set_callbacks(libvlc_instance_t *p_instance,
if (p_cbs != NULL)
{
const vlc_dialog_cbs dialog_cbs = {
.pf_display_error = p_cbs->pf_display_error != NULL ?
display_error_cb : NULL,
.pf_display_login = p_cbs->pf_display_login ?
display_login_cb : NULL,
.pf_display_question = p_cbs->pf_display_question != NULL ?
@ -146,6 +135,14 @@ libvlc_dialog_set_callbacks(libvlc_instance_t *p_instance,
vlc_dialog_provider_set_callbacks(p_libvlc, NULL, NULL);
}
void
libvlc_dialog_set_error_callback(libvlc_instance_t *p_instance,
libvlc_dialog_error_cbs p_cbs, void *p_data)
{
libvlc_int_t *p_libvlc = p_instance->p_libvlc_int;
vlc_dialog_provider_set_error_callback(p_libvlc, p_cbs, p_data);
}
void
libvlc_dialog_set_context(libvlc_dialog_id *p_id, void *p_context)
{

View File

@ -186,7 +186,6 @@ static void updateProgressCallback(void *p_data,
/* subscribe to various interactive dialogues */
const vlc_dialog_cbs cbs = {
displayErrorCallback,
displayLoginCallback,
displayQuestionCallback,
displayProgressCallback,
@ -194,6 +193,7 @@ static void updateProgressCallback(void *p_data,
updateProgressCallback
};
vlc_dialog_provider_set_error_callback(p_intf, displayErrorCallback, (__bridge void *)self);
vlc_dialog_provider_set_callbacks(p_intf, &cbs, (__bridge void *)self);
}
@ -206,6 +206,7 @@ static void updateProgressCallback(void *p_data,
intf_thread_t *p_intf = getIntf();
vlc_dialog_provider_set_callbacks(p_intf, NULL, NULL);
vlc_dialog_provider_set_error_callback(p_intf, NULL, NULL);
}
-(void)awakeFromNib

View File

@ -107,12 +107,20 @@ int DialogErrorModel::count() const
const vlc_dialog_cbs cbs =
{
onError, onLogin, onQuestion, onProgress, onCancelled, onProgressUpdated
onLogin, onQuestion, onProgress, onCancelled, onProgressUpdated
};
vlc_dialog_provider_set_error_callback(intf, onError, this);
vlc_dialog_provider_set_callbacks(intf, &cbs, this);
}
DialogModel::~DialogModel()
{
vlc_dialog_provider_set_callbacks(m_intf, nullptr, nullptr);
vlc_dialog_provider_set_error_callback(m_intf, nullptr, nullptr);
}
//-------------------------------------------------------------------------------------------------
// Interface
//-------------------------------------------------------------------------------------------------

View File

@ -134,6 +134,7 @@ public: // Enums
public:
explicit DialogModel(qt_intf_t * intf, QObject * parent = nullptr);
~DialogModel();
public: // Interface
Q_INVOKABLE void post_login(DialogId dialogId, const QString & username,

View File

@ -40,6 +40,9 @@ struct vlc_dialog_provider
vlc_dialog_cbs cbs;
void * p_cbs_data;
vlc_dialog_error_cbs err_cbs;
void * p_err_cbs_data;
vlc_dialog_ext_update_cb pf_ext_update;
void * p_ext_data;
};
@ -157,6 +160,9 @@ libvlc_InternalDialogInit(libvlc_int_t *p_libvlc)
memset(&p_provider->cbs, 0, sizeof(p_provider->cbs));
p_provider->p_cbs_data = NULL;
p_provider->err_cbs = NULL;
p_provider->p_err_cbs_data = NULL;
p_provider->pf_ext_update = NULL;
p_provider->p_ext_data = NULL;
libvlc_priv(p_libvlc)->p_dialog_provider = p_provider;
@ -271,6 +277,29 @@ vlc_dialog_provider_set_callbacks(vlc_object_t *p_obj,
vlc_mutex_unlock(&p_provider->lock);
}
#undef vlc_dialog_provider_set_error_callback
void
vlc_dialog_provider_set_error_callback(vlc_object_t *p_obj,
vlc_dialog_error_cbs p_cbs, void *p_data)
{
assert(p_obj != NULL);
vlc_dialog_provider *p_provider = get_dialog_provider(p_obj, false);
vlc_mutex_lock(&p_provider->lock);
if (p_cbs == NULL)
{
p_provider->err_cbs = NULL;
p_provider->p_err_cbs_data = NULL;
}
else
{
p_provider->err_cbs = p_cbs;
p_provider->p_err_cbs_data = p_data;
}
vlc_mutex_unlock(&p_provider->lock);
}
static void
dialog_wait_interrupted(void *p_data)
{
@ -328,7 +357,7 @@ dialog_display_error_va(vlc_dialog_provider *p_provider, const char *psz_title,
const char *psz_fmt, va_list ap)
{
vlc_mutex_lock(&p_provider->lock);
if (p_provider->cbs.pf_display_error == NULL)
if (p_provider->err_cbs == NULL)
{
vlc_mutex_unlock(&p_provider->lock);
return VLC_EGENERIC;
@ -341,7 +370,7 @@ dialog_display_error_va(vlc_dialog_provider *p_provider, const char *psz_title,
return VLC_ENOMEM;
}
p_provider->cbs.pf_display_error(p_provider->p_cbs_data, psz_title, psz_text);
p_provider->err_cbs(p_provider->p_err_cbs_data, psz_title, psz_text);
free(psz_text);
vlc_mutex_unlock(&p_provider->lock);

View File

@ -533,6 +533,7 @@ vlc_dialog_id_post_login
vlc_dialog_id_set_context
vlc_dialog_is_cancelled
vlc_dialog_provider_set_callbacks
vlc_dialog_provider_set_error_callback
vlc_dialog_provider_set_ext_callback
vlc_dialog_release
vlc_dialog_update_progress

View File

@ -294,7 +294,6 @@ main(int i_argc, char *ppsz_argv[])
printf("testing dialog callbacks\n");
const vlc_dialog_cbs cbs = {
.pf_display_error = display_error_cb,
.pf_display_login = display_login_cb,
.pf_display_question = display_question_cb,
.pf_display_progress = display_progress_cb,
@ -303,7 +302,9 @@ main(int i_argc, char *ppsz_argv[])
};
struct cb_answer ans = { 0 };
vlc_dialog_provider_set_callbacks(p_libvlc->p_libvlc_int, &cbs, &ans);
vlc_dialog_provider_set_error_callback(p_libvlc->p_libvlc_int, &display_error_cb, &ans);
test_dialogs(VLC_OBJECT(p_libvlc->p_libvlc_int), &ans, 100000);
vlc_dialog_provider_set_error_callback(p_libvlc->p_libvlc_int, NULL, NULL);
vlc_dialog_provider_set_callbacks(p_libvlc->p_libvlc_int, NULL, NULL);
libvlc_release(p_libvlc);