1 /*****************************************************************************
2 * dialog.c: User dialog functions
3 *****************************************************************************
4 * Copyright © 2009 Rémi Denis-Courmont
5 * Copyright © 2016 VLC authors and VideoLAN
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as published by
9 * the Free Software Foundation; either version 2.1 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this program; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
20 *****************************************************************************/
22 /** @ingroup vlc_dialog */
29 #include <vlc_common.h>
30 #include <vlc_dialog.h>
31 #include <vlc_interrupt.h>
32 #include <vlc_extensions.h>
36 struct vlc_dialog_provider
39 vlc_array_t dialog_array
;
43 vlc_dialog_ext_update_cb pf_ext_update
;
57 enum dialog_type i_type
;
75 enum dialog_type i_type
;
76 const char *psz_title
;
83 const char *psz_default_username
;
88 vlc_dialog_question_type i_type
;
89 const char *psz_cancel
;
90 const char *psz_action1
;
91 const char *psz_action2
;
97 const char *psz_cancel
;
106 enum dialog_type i_type
;
111 bool b_progress_indeterminate
;
112 char * psz_progress_text
;
113 struct dialog_answer answer
;
116 struct dialog_i11e_context
118 vlc_dialog_provider
* p_provider
;
119 vlc_dialog_id
* p_id
;
122 static inline vlc_dialog_provider
*
123 get_dialog_provider(vlc_object_t
*p_obj
, bool b_check_interact
)
125 if (b_check_interact
&& p_obj
->obj
.flags
& OBJECT_FLAGS_NOINTERACT
)
128 vlc_dialog_provider
*p_provider
=
129 libvlc_priv(p_obj
->obj
.libvlc
)->p_dialog_provider
;
130 assert(p_provider
!= NULL
);
135 dialog_id_release(vlc_dialog_id
*p_id
)
137 if (p_id
->answer
.i_type
== VLC_DIALOG_LOGIN
)
139 free(p_id
->answer
.u
.login
.psz_username
);
140 free(p_id
->answer
.u
.login
.psz_password
);
142 free(p_id
->psz_progress_text
);
143 vlc_mutex_destroy(&p_id
->lock
);
144 vlc_cond_destroy(&p_id
->wait
);
149 libvlc_InternalDialogInit(libvlc_int_t
*p_libvlc
)
151 assert(p_libvlc
!= NULL
);
152 vlc_dialog_provider
*p_provider
= malloc(sizeof(*p_provider
));
153 if (p_provider
== NULL
)
156 vlc_mutex_init(&p_provider
->lock
);
157 vlc_array_init(&p_provider
->dialog_array
);
159 memset(&p_provider
->cbs
, 0, sizeof(p_provider
->cbs
));
160 p_provider
->p_cbs_data
= NULL
;
162 p_provider
->pf_ext_update
= NULL
;
163 p_provider
->p_ext_data
= NULL
;
164 libvlc_priv(p_libvlc
)->p_dialog_provider
= p_provider
;
170 dialog_cancel_locked(vlc_dialog_provider
*p_provider
, vlc_dialog_id
*p_id
)
172 vlc_mutex_lock(&p_id
->lock
);
173 if (p_id
->b_cancelled
|| p_id
->b_answered
)
175 vlc_mutex_unlock(&p_id
->lock
);
178 p_id
->b_cancelled
= true;
179 vlc_mutex_unlock(&p_id
->lock
);
181 p_provider
->cbs
.pf_cancel(p_provider
->p_cbs_data
, p_id
);
184 static vlc_dialog_id
*
185 dialog_add_locked(vlc_dialog_provider
*p_provider
, enum dialog_type i_type
)
187 vlc_dialog_id
*p_id
= calloc(1, sizeof(*p_id
));
191 vlc_mutex_init(&p_id
->lock
);
192 vlc_cond_init(&p_id
->wait
);
194 p_id
->i_type
= i_type
;
195 p_id
->i_refcount
= 2; /* provider and callbacks */
197 vlc_array_append(&p_provider
->dialog_array
, p_id
);
202 dialog_remove_locked(vlc_dialog_provider
*p_provider
, vlc_dialog_id
*p_id
)
204 ssize_t i_idx
= vlc_array_index_of_item(&p_provider
->dialog_array
, p_id
);
206 vlc_array_remove(&p_provider
->dialog_array
, i_idx
);
208 vlc_mutex_lock(&p_id
->lock
);
210 if (p_id
->i_refcount
== 0)
212 vlc_mutex_unlock(&p_id
->lock
);
213 dialog_id_release(p_id
);
216 vlc_mutex_unlock(&p_id
->lock
);
220 dialog_clear_all_locked(vlc_dialog_provider
*p_provider
)
222 for (size_t i
= 0; i
< vlc_array_count(&p_provider
->dialog_array
); ++i
)
224 vlc_dialog_id
*p_id
=
225 vlc_array_item_at_index(&p_provider
->dialog_array
, i
);
226 dialog_cancel_locked(p_provider
, p_id
);
231 libvlc_InternalDialogClean(libvlc_int_t
*p_libvlc
)
233 assert(p_libvlc
!= NULL
);
234 vlc_dialog_provider
*p_provider
= libvlc_priv(p_libvlc
)->p_dialog_provider
;
236 if (p_provider
== NULL
)
238 vlc_mutex_lock(&p_provider
->lock
);
239 dialog_clear_all_locked(p_provider
);
240 vlc_mutex_unlock(&p_provider
->lock
);
242 vlc_mutex_destroy(&p_provider
->lock
);
244 libvlc_priv(p_libvlc
)->p_dialog_provider
= NULL
;
247 #undef vlc_dialog_provider_set_callbacks
249 vlc_dialog_provider_set_callbacks(vlc_object_t
*p_obj
,
250 const vlc_dialog_cbs
*p_cbs
, void *p_data
)
252 assert(p_obj
!= NULL
);
253 vlc_dialog_provider
*p_provider
= get_dialog_provider(p_obj
, false);
255 vlc_mutex_lock(&p_provider
->lock
);
256 dialog_clear_all_locked(p_provider
);
260 memset(&p_provider
->cbs
, 0, sizeof(p_provider
->cbs
));
261 p_provider
->p_cbs_data
= NULL
;
265 p_provider
->cbs
= *p_cbs
;
266 p_provider
->p_cbs_data
= p_data
;
268 vlc_mutex_unlock(&p_provider
->lock
);
272 dialog_wait_interrupted(void *p_data
)
274 struct dialog_i11e_context
*p_context
= p_data
;
275 vlc_dialog_provider
*p_provider
= p_context
->p_provider
;
276 vlc_dialog_id
*p_id
= p_context
->p_id
;
278 vlc_mutex_lock(&p_provider
->lock
);
279 dialog_cancel_locked(p_provider
, p_id
);
280 vlc_mutex_unlock(&p_provider
->lock
);
282 vlc_mutex_lock(&p_id
->lock
);
283 vlc_cond_signal(&p_id
->wait
);
284 vlc_mutex_unlock(&p_id
->lock
);
288 dialog_wait(vlc_dialog_provider
*p_provider
, vlc_dialog_id
*p_id
,
289 enum dialog_type i_type
, struct dialog_answer
*p_answer
)
291 struct dialog_i11e_context context
= {
292 .p_provider
= p_provider
,
295 vlc_interrupt_register(dialog_wait_interrupted
, &context
);
297 vlc_mutex_lock(&p_id
->lock
);
298 /* Wait for the dialog to be dismissed, interrupted or answered */
299 while (!p_id
->b_cancelled
&& !p_id
->b_answered
)
300 vlc_cond_wait(&p_id
->wait
, &p_id
->lock
);
303 if (p_id
->b_cancelled
)
305 else if (p_id
->answer
.i_type
!= i_type
)
306 i_ret
= VLC_EGENERIC
;
310 memcpy(p_answer
, &p_id
->answer
, sizeof(p_id
->answer
));
311 memset(&p_id
->answer
, 0, sizeof(p_id
->answer
));
314 vlc_mutex_unlock(&p_id
->lock
);
315 vlc_interrupt_unregister();
317 vlc_mutex_lock(&p_provider
->lock
);
318 dialog_remove_locked(p_provider
, p_id
);
319 vlc_mutex_unlock(&p_provider
->lock
);
324 dialog_display_error_va(vlc_dialog_provider
*p_provider
, const char *psz_title
,
325 const char *psz_fmt
, va_list ap
)
327 vlc_mutex_lock(&p_provider
->lock
);
328 if (p_provider
->cbs
.pf_display_error
== NULL
)
330 vlc_mutex_unlock(&p_provider
->lock
);
335 if (vasprintf(&psz_text
, psz_fmt
, ap
) == -1)
337 vlc_mutex_unlock(&p_provider
->lock
);
341 p_provider
->cbs
.pf_display_error(p_provider
->p_cbs_data
, psz_title
, psz_text
);
343 vlc_mutex_unlock(&p_provider
->lock
);
349 vlc_dialog_display_error_va(vlc_object_t
*p_obj
, const char *psz_title
,
350 const char *psz_fmt
, va_list ap
)
352 assert(p_obj
!= NULL
&& psz_title
!= NULL
&& psz_fmt
!= NULL
);
354 vlc_dialog_provider
*p_provider
= get_dialog_provider(p_obj
, true);
356 if (p_provider
!= NULL
)
357 i_ret
= dialog_display_error_va(p_provider
, psz_title
, psz_fmt
, ap
);
359 i_ret
= VLC_EGENERIC
;
361 if (i_ret
!= VLC_SUCCESS
)
363 msg_Err(p_obj
, "%s", psz_title
);
364 msg_GenericVa(p_obj
, VLC_MSG_ERR
, psz_fmt
, ap
);
370 #undef vlc_dialog_display_error
372 vlc_dialog_display_error(vlc_object_t
*p_obj
, const char *psz_title
,
373 const char *psz_fmt
, ...)
375 assert(psz_fmt
!= NULL
);
377 va_start(ap
, psz_fmt
);
378 int i_ret
= vlc_dialog_display_error_va(p_obj
, psz_title
, psz_fmt
, ap
);
384 dialog_display_login_va(vlc_dialog_provider
*p_provider
, vlc_dialog_id
**pp_id
,
385 const char *psz_default_username
, bool b_ask_store
,
386 const char *psz_title
, const char *psz_fmt
, va_list ap
)
388 vlc_mutex_lock(&p_provider
->lock
);
389 if (p_provider
->cbs
.pf_display_login
== NULL
390 || p_provider
->cbs
.pf_cancel
== NULL
)
392 vlc_mutex_unlock(&p_provider
->lock
);
397 if (vasprintf(&psz_text
, psz_fmt
, ap
) == -1)
399 vlc_mutex_unlock(&p_provider
->lock
);
403 vlc_dialog_id
*p_id
= dialog_add_locked(p_provider
, VLC_DIALOG_LOGIN
);
407 vlc_mutex_unlock(&p_provider
->lock
);
410 p_provider
->cbs
.pf_display_login(p_provider
->p_cbs_data
, p_id
, psz_title
,
411 psz_text
, psz_default_username
, b_ask_store
);
413 vlc_mutex_unlock(&p_provider
->lock
);
420 vlc_dialog_wait_login_va(vlc_object_t
*p_obj
, char **ppsz_username
,
421 char **ppsz_password
, bool *p_store
,
422 const char *psz_default_username
,
423 const char *psz_title
, const char *psz_fmt
, va_list ap
)
425 assert(p_obj
!= NULL
&& ppsz_username
!= NULL
&& ppsz_password
!= NULL
426 && psz_fmt
!= NULL
&& psz_title
!= NULL
);
428 vlc_dialog_provider
*p_provider
= get_dialog_provider(p_obj
, true);
429 if (p_provider
== NULL
)
433 int i_ret
= dialog_display_login_va(p_provider
, &p_id
, psz_default_username
,
434 p_store
!= NULL
, psz_title
, psz_fmt
, ap
);
435 if (i_ret
< 0 || p_id
== NULL
)
438 struct dialog_answer answer
;
439 i_ret
= dialog_wait(p_provider
, p_id
, VLC_DIALOG_LOGIN
, &answer
);
443 *ppsz_username
= answer
.u
.login
.psz_username
;
444 *ppsz_password
= answer
.u
.login
.psz_password
;
446 *p_store
= answer
.u
.login
.b_store
;
451 #undef vlc_dialog_wait_login
453 vlc_dialog_wait_login(vlc_object_t
*p_obj
, char **ppsz_username
,
454 char **ppsz_password
, bool *p_store
,
455 const char *psz_default_username
, const char *psz_title
,
456 const char *psz_fmt
, ...)
458 assert(psz_fmt
!= NULL
);
460 va_start(ap
, psz_fmt
);
461 int i_ret
= vlc_dialog_wait_login_va(p_obj
, ppsz_username
, ppsz_password
,
462 p_store
,psz_default_username
,
463 psz_title
, psz_fmt
, ap
);
469 dialog_display_question_va(vlc_dialog_provider
*p_provider
, vlc_dialog_id
**pp_id
,
470 vlc_dialog_question_type i_type
,
471 const char *psz_cancel
, const char *psz_action1
,
472 const char *psz_action2
, const char *psz_title
,
473 const char *psz_fmt
, va_list ap
)
475 vlc_mutex_lock(&p_provider
->lock
);
476 if (p_provider
->cbs
.pf_display_question
== NULL
477 || p_provider
->cbs
.pf_cancel
== NULL
)
479 vlc_mutex_unlock(&p_provider
->lock
);
484 if (vasprintf(&psz_text
, psz_fmt
, ap
) == -1)
486 vlc_mutex_unlock(&p_provider
->lock
);
490 vlc_dialog_id
*p_id
= dialog_add_locked(p_provider
, VLC_DIALOG_QUESTION
);
494 vlc_mutex_unlock(&p_provider
->lock
);
497 p_provider
->cbs
.pf_display_question(p_provider
->p_cbs_data
, p_id
, psz_title
,
498 psz_text
, i_type
, psz_cancel
, psz_action1
,
501 vlc_mutex_unlock(&p_provider
->lock
);
508 vlc_dialog_wait_question_va(vlc_object_t
*p_obj
,
509 vlc_dialog_question_type i_type
,
510 const char *psz_cancel
, const char *psz_action1
,
511 const char *psz_action2
, const char *psz_title
,
512 const char *psz_fmt
, va_list ap
)
514 assert(p_obj
!= NULL
&& psz_fmt
!= NULL
&& psz_title
!= NULL
515 && psz_cancel
!= NULL
);
517 vlc_dialog_provider
*p_provider
= get_dialog_provider(p_obj
, true);
518 if (p_provider
== NULL
)
522 int i_ret
= dialog_display_question_va(p_provider
, &p_id
, i_type
,
523 psz_cancel
, psz_action1
,
524 psz_action2
, psz_title
, psz_fmt
, ap
);
525 if (i_ret
< 0 || p_id
== NULL
)
528 struct dialog_answer answer
;
529 i_ret
= dialog_wait(p_provider
, p_id
, VLC_DIALOG_QUESTION
, &answer
);
533 if (answer
.u
.question
.i_action
!= 1 && answer
.u
.question
.i_action
!= 2)
536 return answer
.u
.question
.i_action
;
539 #undef vlc_dialog_wait_question
541 vlc_dialog_wait_question(vlc_object_t
*p_obj
,
542 vlc_dialog_question_type i_type
,
543 const char *psz_cancel
, const char *psz_action1
,
544 const char *psz_action2
, const char *psz_title
,
545 const char *psz_fmt
, ...)
547 assert(psz_fmt
!= NULL
);
549 va_start(ap
, psz_fmt
);
550 int i_ret
= vlc_dialog_wait_question_va(p_obj
, i_type
, psz_cancel
,
551 psz_action1
, psz_action2
, psz_title
,
558 display_progress_va(vlc_dialog_provider
*p_provider
, vlc_dialog_id
**pp_id
,
559 bool b_indeterminate
, float f_position
,
560 const char *psz_cancel
, const char *psz_title
,
561 const char *psz_fmt
, va_list ap
)
563 vlc_mutex_lock(&p_provider
->lock
);
564 if (p_provider
->cbs
.pf_display_progress
== NULL
565 || p_provider
->cbs
.pf_update_progress
== NULL
566 || p_provider
->cbs
.pf_cancel
== NULL
)
568 vlc_mutex_unlock(&p_provider
->lock
);
573 if (vasprintf(&psz_text
, psz_fmt
, ap
) == -1)
575 vlc_mutex_unlock(&p_provider
->lock
);
579 vlc_dialog_id
*p_id
= dialog_add_locked(p_provider
, VLC_DIALOG_PROGRESS
);
583 vlc_mutex_unlock(&p_provider
->lock
);
586 p_id
->b_progress_indeterminate
= b_indeterminate
;
587 p_id
->psz_progress_text
= psz_text
;
588 p_provider
->cbs
.pf_display_progress(p_provider
->p_cbs_data
, p_id
, psz_title
,
589 psz_text
, b_indeterminate
, f_position
,
591 vlc_mutex_unlock(&p_provider
->lock
);
598 vlc_dialog_display_progress_va(vlc_object_t
*p_obj
, bool b_indeterminate
,
599 float f_position
, const char *psz_cancel
,
600 const char *psz_title
, const char *psz_fmt
,
603 assert(p_obj
!= NULL
&& psz_title
!= NULL
&& psz_fmt
!= NULL
);
605 vlc_dialog_provider
*p_provider
= get_dialog_provider(p_obj
, true);
606 if (p_provider
== NULL
)
609 int i_ret
= display_progress_va(p_provider
, &p_id
, b_indeterminate
,
610 f_position
, psz_cancel
, psz_title
, psz_fmt
,
612 return i_ret
== VLC_SUCCESS
? p_id
: NULL
;
615 #undef vlc_dialog_display_progress
617 vlc_dialog_display_progress(vlc_object_t
*p_obj
, bool b_indeterminate
,
618 float f_position
, const char *psz_cancel
,
619 const char *psz_title
, const char *psz_fmt
, ...)
621 assert(psz_fmt
!= NULL
);
623 va_start(ap
, psz_fmt
);
624 vlc_dialog_id
*p_id
=
625 vlc_dialog_display_progress_va(p_obj
, b_indeterminate
, f_position
,
626 psz_cancel
, psz_title
, psz_fmt
, ap
);
632 dialog_update_progress(vlc_object_t
*p_obj
, vlc_dialog_id
*p_id
, float f_value
,
635 assert(p_obj
!= NULL
&& p_id
!= NULL
);
636 vlc_dialog_provider
*p_provider
= get_dialog_provider(p_obj
, false);
638 vlc_mutex_lock(&p_provider
->lock
);
639 if (p_provider
->cbs
.pf_update_progress
== NULL
||
640 vlc_dialog_is_cancelled(p_obj
, p_id
))
642 vlc_mutex_unlock(&p_provider
->lock
);
647 if (p_id
->b_progress_indeterminate
)
650 if (psz_text
!= NULL
)
652 free(p_id
->psz_progress_text
);
653 p_id
->psz_progress_text
= psz_text
;
655 p_provider
->cbs
.pf_update_progress(p_provider
->p_cbs_data
, p_id
, f_value
,
656 p_id
->psz_progress_text
);
658 vlc_mutex_unlock(&p_provider
->lock
);
662 #undef vlc_dialog_update_progress
664 vlc_dialog_update_progress(vlc_object_t
*p_obj
, vlc_dialog_id
*p_id
,
667 return dialog_update_progress(p_obj
, p_id
, f_value
, NULL
);
671 vlc_dialog_update_progress_text_va(vlc_object_t
*p_obj
, vlc_dialog_id
*p_id
,
672 float f_value
, const char *psz_fmt
,
675 assert(psz_fmt
!= NULL
);
678 if (vasprintf(&psz_text
, psz_fmt
, ap
) == -1)
680 return dialog_update_progress(p_obj
, p_id
, f_value
, psz_text
);
683 #undef vlc_dialog_update_progress_text
685 vlc_dialog_update_progress_text(vlc_object_t
*p_obj
, vlc_dialog_id
*p_id
,
686 float f_value
, const char *psz_fmt
, ...)
688 assert(psz_fmt
!= NULL
);
690 va_start(ap
, psz_fmt
);
691 int i_ret
= vlc_dialog_update_progress_text_va(p_obj
, p_id
, f_value
,
697 #undef vlc_dialog_release
699 vlc_dialog_release(vlc_object_t
*p_obj
, vlc_dialog_id
*p_id
)
701 assert(p_obj
!= NULL
&& p_id
!= NULL
);
702 vlc_dialog_provider
*p_provider
= get_dialog_provider(p_obj
, false);
704 vlc_mutex_lock(&p_provider
->lock
);
705 dialog_cancel_locked(p_provider
, p_id
);
706 dialog_remove_locked(p_provider
, p_id
);
707 vlc_mutex_unlock(&p_provider
->lock
);
710 #undef vlc_dialog_is_cancelled
712 vlc_dialog_is_cancelled(vlc_object_t
*p_obj
, vlc_dialog_id
*p_id
)
715 assert(p_id
!= NULL
);
717 vlc_mutex_lock(&p_id
->lock
);
718 bool b_cancelled
= p_id
->b_cancelled
;
719 vlc_mutex_unlock(&p_id
->lock
);
724 vlc_dialog_id_set_context(vlc_dialog_id
*p_id
, void *p_context
)
726 vlc_mutex_lock(&p_id
->lock
);
727 p_id
->p_context
= p_context
;
728 vlc_mutex_unlock(&p_id
->lock
);
732 vlc_dialog_id_get_context(vlc_dialog_id
*p_id
)
734 assert(p_id
!= NULL
);
735 vlc_mutex_lock(&p_id
->lock
);
736 void *p_context
= p_id
->p_context
;
737 vlc_mutex_unlock(&p_id
->lock
);
742 dialog_id_post(vlc_dialog_id
*p_id
, struct dialog_answer
*p_answer
)
744 vlc_mutex_lock(&p_id
->lock
);
745 if (p_answer
== NULL
)
747 p_id
->b_cancelled
= true;
751 p_id
->answer
= *p_answer
;
752 p_id
->b_answered
= true;
755 if (p_id
->i_refcount
> 0)
757 vlc_cond_signal(&p_id
->wait
);
758 vlc_mutex_unlock(&p_id
->lock
);
762 vlc_mutex_unlock(&p_id
->lock
);
763 dialog_id_release(p_id
);
769 vlc_dialog_id_post_login(vlc_dialog_id
*p_id
, const char *psz_username
,
770 const char *psz_password
, bool b_store
)
772 assert(p_id
!= NULL
&& psz_username
!= NULL
&& psz_password
!= NULL
);
774 struct dialog_answer answer
= {
775 .i_type
= VLC_DIALOG_LOGIN
,
778 .psz_username
= strdup(psz_username
),
779 .psz_password
= strdup(psz_password
),
782 if (answer
.u
.login
.psz_username
== NULL
783 || answer
.u
.login
.psz_password
== NULL
)
785 free(answer
.u
.login
.psz_username
);
786 free(answer
.u
.login
.psz_password
);
787 dialog_id_post(p_id
, NULL
);
791 return dialog_id_post(p_id
, &answer
);
795 vlc_dialog_id_post_action(vlc_dialog_id
*p_id
, int i_action
)
797 assert(p_id
!= NULL
);
799 struct dialog_answer answer
= {
800 .i_type
= VLC_DIALOG_QUESTION
,
801 .u
.question
= { .i_action
= i_action
},
804 return dialog_id_post(p_id
, &answer
);
808 vlc_dialog_id_dismiss(vlc_dialog_id
*p_id
)
810 return dialog_id_post(p_id
, NULL
);
813 #undef vlc_dialog_provider_set_ext_callback
815 vlc_dialog_provider_set_ext_callback(vlc_object_t
*p_obj
,
816 vlc_dialog_ext_update_cb pf_update
,
819 assert(p_obj
!= NULL
);
820 vlc_dialog_provider
*p_provider
= get_dialog_provider(p_obj
, false);
822 vlc_mutex_lock(&p_provider
->lock
);
824 p_provider
->pf_ext_update
= pf_update
;
825 p_provider
->p_ext_data
= p_data
;
827 vlc_mutex_unlock(&p_provider
->lock
);
830 #undef vlc_ext_dialog_update
832 vlc_ext_dialog_update(vlc_object_t
*p_obj
, extension_dialog_t
*p_ext_dialog
)
834 assert(p_obj
!= NULL
);
835 vlc_dialog_provider
*p_provider
= get_dialog_provider(p_obj
, false);
837 vlc_mutex_lock(&p_provider
->lock
);
838 if (p_provider
->pf_ext_update
== NULL
)
840 vlc_mutex_unlock(&p_provider
->lock
);
843 p_provider
->pf_ext_update(p_ext_dialog
, p_provider
->p_ext_data
);
844 vlc_mutex_unlock(&p_provider
->lock
);