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
));
192 if(vlc_array_append(&p_provider
->dialog_array
, p_id
))
198 vlc_mutex_init(&p_id
->lock
);
199 vlc_cond_init(&p_id
->wait
);
201 p_id
->i_type
= i_type
;
202 p_id
->i_refcount
= 2; /* provider and callbacks */
208 dialog_remove_locked(vlc_dialog_provider
*p_provider
, vlc_dialog_id
*p_id
)
210 ssize_t i_idx
= vlc_array_index_of_item(&p_provider
->dialog_array
, p_id
);
212 vlc_array_remove(&p_provider
->dialog_array
, i_idx
);
214 vlc_mutex_lock(&p_id
->lock
);
216 if (p_id
->i_refcount
== 0)
218 vlc_mutex_unlock(&p_id
->lock
);
219 dialog_id_release(p_id
);
222 vlc_mutex_unlock(&p_id
->lock
);
226 dialog_clear_all_locked(vlc_dialog_provider
*p_provider
)
228 for (size_t i
= 0; i
< vlc_array_count(&p_provider
->dialog_array
); ++i
)
230 vlc_dialog_id
*p_id
=
231 vlc_array_item_at_index(&p_provider
->dialog_array
, i
);
232 dialog_cancel_locked(p_provider
, p_id
);
237 libvlc_InternalDialogClean(libvlc_int_t
*p_libvlc
)
239 assert(p_libvlc
!= NULL
);
240 vlc_dialog_provider
*p_provider
= libvlc_priv(p_libvlc
)->p_dialog_provider
;
242 if (p_provider
== NULL
)
244 vlc_mutex_lock(&p_provider
->lock
);
245 dialog_clear_all_locked(p_provider
);
246 vlc_mutex_unlock(&p_provider
->lock
);
248 vlc_mutex_destroy(&p_provider
->lock
);
250 libvlc_priv(p_libvlc
)->p_dialog_provider
= NULL
;
253 #undef vlc_dialog_provider_set_callbacks
255 vlc_dialog_provider_set_callbacks(vlc_object_t
*p_obj
,
256 const vlc_dialog_cbs
*p_cbs
, void *p_data
)
258 assert(p_obj
!= NULL
);
259 vlc_dialog_provider
*p_provider
= get_dialog_provider(p_obj
, false);
261 vlc_mutex_lock(&p_provider
->lock
);
262 dialog_clear_all_locked(p_provider
);
266 memset(&p_provider
->cbs
, 0, sizeof(p_provider
->cbs
));
267 p_provider
->p_cbs_data
= NULL
;
271 p_provider
->cbs
= *p_cbs
;
272 p_provider
->p_cbs_data
= p_data
;
274 vlc_mutex_unlock(&p_provider
->lock
);
278 dialog_wait_interrupted(void *p_data
)
280 struct dialog_i11e_context
*p_context
= p_data
;
281 vlc_dialog_provider
*p_provider
= p_context
->p_provider
;
282 vlc_dialog_id
*p_id
= p_context
->p_id
;
284 vlc_mutex_lock(&p_provider
->lock
);
285 dialog_cancel_locked(p_provider
, p_id
);
286 vlc_mutex_unlock(&p_provider
->lock
);
288 vlc_mutex_lock(&p_id
->lock
);
289 vlc_cond_signal(&p_id
->wait
);
290 vlc_mutex_unlock(&p_id
->lock
);
294 dialog_wait(vlc_dialog_provider
*p_provider
, vlc_dialog_id
*p_id
,
295 enum dialog_type i_type
, struct dialog_answer
*p_answer
)
297 struct dialog_i11e_context context
= {
298 .p_provider
= p_provider
,
301 vlc_interrupt_register(dialog_wait_interrupted
, &context
);
303 vlc_mutex_lock(&p_id
->lock
);
304 /* Wait for the dialog to be dismissed, interrupted or answered */
305 while (!p_id
->b_cancelled
&& !p_id
->b_answered
)
306 vlc_cond_wait(&p_id
->wait
, &p_id
->lock
);
309 if (p_id
->b_cancelled
)
311 else if (p_id
->answer
.i_type
!= i_type
)
312 i_ret
= VLC_EGENERIC
;
316 memcpy(p_answer
, &p_id
->answer
, sizeof(p_id
->answer
));
317 memset(&p_id
->answer
, 0, sizeof(p_id
->answer
));
320 vlc_mutex_unlock(&p_id
->lock
);
321 vlc_interrupt_unregister();
323 vlc_mutex_lock(&p_provider
->lock
);
324 dialog_remove_locked(p_provider
, p_id
);
325 vlc_mutex_unlock(&p_provider
->lock
);
330 dialog_display_error_va(vlc_dialog_provider
*p_provider
, const char *psz_title
,
331 const char *psz_fmt
, va_list ap
)
333 vlc_mutex_lock(&p_provider
->lock
);
334 if (p_provider
->cbs
.pf_display_error
== NULL
)
336 vlc_mutex_unlock(&p_provider
->lock
);
341 if (vasprintf(&psz_text
, psz_fmt
, ap
) == -1)
343 vlc_mutex_unlock(&p_provider
->lock
);
347 p_provider
->cbs
.pf_display_error(p_provider
->p_cbs_data
, psz_title
, psz_text
);
349 vlc_mutex_unlock(&p_provider
->lock
);
355 vlc_dialog_display_error_va(vlc_object_t
*p_obj
, const char *psz_title
,
356 const char *psz_fmt
, va_list ap
)
358 assert(p_obj
!= NULL
&& psz_title
!= NULL
&& psz_fmt
!= NULL
);
360 vlc_dialog_provider
*p_provider
= get_dialog_provider(p_obj
, true);
362 if (p_provider
!= NULL
)
363 i_ret
= dialog_display_error_va(p_provider
, psz_title
, psz_fmt
, ap
);
365 i_ret
= VLC_EGENERIC
;
367 if (i_ret
!= VLC_SUCCESS
)
369 msg_Err(p_obj
, "%s", psz_title
);
370 msg_GenericVa(p_obj
, VLC_MSG_ERR
, psz_fmt
, ap
);
376 #undef vlc_dialog_display_error
378 vlc_dialog_display_error(vlc_object_t
*p_obj
, const char *psz_title
,
379 const char *psz_fmt
, ...)
381 assert(psz_fmt
!= NULL
);
383 va_start(ap
, psz_fmt
);
384 int i_ret
= vlc_dialog_display_error_va(p_obj
, psz_title
, psz_fmt
, ap
);
390 dialog_display_login_va(vlc_dialog_provider
*p_provider
, vlc_dialog_id
**pp_id
,
391 const char *psz_default_username
, bool b_ask_store
,
392 const char *psz_title
, const char *psz_fmt
, va_list ap
)
394 vlc_mutex_lock(&p_provider
->lock
);
395 if (p_provider
->cbs
.pf_display_login
== NULL
396 || p_provider
->cbs
.pf_cancel
== NULL
)
398 vlc_mutex_unlock(&p_provider
->lock
);
403 if (vasprintf(&psz_text
, psz_fmt
, ap
) == -1)
405 vlc_mutex_unlock(&p_provider
->lock
);
409 vlc_dialog_id
*p_id
= dialog_add_locked(p_provider
, VLC_DIALOG_LOGIN
);
413 vlc_mutex_unlock(&p_provider
->lock
);
416 p_provider
->cbs
.pf_display_login(p_provider
->p_cbs_data
, p_id
, psz_title
,
417 psz_text
, psz_default_username
, b_ask_store
);
419 vlc_mutex_unlock(&p_provider
->lock
);
426 vlc_dialog_wait_login_va(vlc_object_t
*p_obj
, char **ppsz_username
,
427 char **ppsz_password
, bool *p_store
,
428 const char *psz_default_username
,
429 const char *psz_title
, const char *psz_fmt
, va_list ap
)
431 assert(p_obj
!= NULL
&& ppsz_username
!= NULL
&& ppsz_password
!= NULL
432 && psz_fmt
!= NULL
&& psz_title
!= NULL
);
434 vlc_dialog_provider
*p_provider
= get_dialog_provider(p_obj
, true);
435 if (p_provider
== NULL
)
439 int i_ret
= dialog_display_login_va(p_provider
, &p_id
, psz_default_username
,
440 p_store
!= NULL
, psz_title
, psz_fmt
, ap
);
441 if (i_ret
< 0 || p_id
== NULL
)
444 struct dialog_answer answer
;
445 i_ret
= dialog_wait(p_provider
, p_id
, VLC_DIALOG_LOGIN
, &answer
);
449 *ppsz_username
= answer
.u
.login
.psz_username
;
450 *ppsz_password
= answer
.u
.login
.psz_password
;
452 *p_store
= answer
.u
.login
.b_store
;
457 #undef vlc_dialog_wait_login
459 vlc_dialog_wait_login(vlc_object_t
*p_obj
, char **ppsz_username
,
460 char **ppsz_password
, bool *p_store
,
461 const char *psz_default_username
, const char *psz_title
,
462 const char *psz_fmt
, ...)
464 assert(psz_fmt
!= NULL
);
466 va_start(ap
, psz_fmt
);
467 int i_ret
= vlc_dialog_wait_login_va(p_obj
, ppsz_username
, ppsz_password
,
468 p_store
,psz_default_username
,
469 psz_title
, psz_fmt
, ap
);
475 dialog_display_question_va(vlc_dialog_provider
*p_provider
, vlc_dialog_id
**pp_id
,
476 vlc_dialog_question_type i_type
,
477 const char *psz_cancel
, const char *psz_action1
,
478 const char *psz_action2
, const char *psz_title
,
479 const char *psz_fmt
, va_list ap
)
481 vlc_mutex_lock(&p_provider
->lock
);
482 if (p_provider
->cbs
.pf_display_question
== NULL
483 || p_provider
->cbs
.pf_cancel
== NULL
)
485 vlc_mutex_unlock(&p_provider
->lock
);
490 if (vasprintf(&psz_text
, psz_fmt
, ap
) == -1)
492 vlc_mutex_unlock(&p_provider
->lock
);
496 vlc_dialog_id
*p_id
= dialog_add_locked(p_provider
, VLC_DIALOG_QUESTION
);
500 vlc_mutex_unlock(&p_provider
->lock
);
503 p_provider
->cbs
.pf_display_question(p_provider
->p_cbs_data
, p_id
, psz_title
,
504 psz_text
, i_type
, psz_cancel
, psz_action1
,
507 vlc_mutex_unlock(&p_provider
->lock
);
514 vlc_dialog_wait_question_va(vlc_object_t
*p_obj
,
515 vlc_dialog_question_type i_type
,
516 const char *psz_cancel
, const char *psz_action1
,
517 const char *psz_action2
, const char *psz_title
,
518 const char *psz_fmt
, va_list ap
)
520 assert(p_obj
!= NULL
&& psz_fmt
!= NULL
&& psz_title
!= NULL
521 && psz_cancel
!= NULL
);
523 vlc_dialog_provider
*p_provider
= get_dialog_provider(p_obj
, true);
524 if (p_provider
== NULL
)
528 int i_ret
= dialog_display_question_va(p_provider
, &p_id
, i_type
,
529 psz_cancel
, psz_action1
,
530 psz_action2
, psz_title
, psz_fmt
, ap
);
531 if (i_ret
< 0 || p_id
== NULL
)
534 struct dialog_answer answer
;
535 i_ret
= dialog_wait(p_provider
, p_id
, VLC_DIALOG_QUESTION
, &answer
);
539 if (answer
.u
.question
.i_action
!= 1 && answer
.u
.question
.i_action
!= 2)
542 return answer
.u
.question
.i_action
;
545 #undef vlc_dialog_wait_question
547 vlc_dialog_wait_question(vlc_object_t
*p_obj
,
548 vlc_dialog_question_type i_type
,
549 const char *psz_cancel
, const char *psz_action1
,
550 const char *psz_action2
, const char *psz_title
,
551 const char *psz_fmt
, ...)
553 assert(psz_fmt
!= NULL
);
555 va_start(ap
, psz_fmt
);
556 int i_ret
= vlc_dialog_wait_question_va(p_obj
, i_type
, psz_cancel
,
557 psz_action1
, psz_action2
, psz_title
,
564 display_progress_va(vlc_dialog_provider
*p_provider
, vlc_dialog_id
**pp_id
,
565 bool b_indeterminate
, float f_position
,
566 const char *psz_cancel
, const char *psz_title
,
567 const char *psz_fmt
, va_list ap
)
569 vlc_mutex_lock(&p_provider
->lock
);
570 if (p_provider
->cbs
.pf_display_progress
== NULL
571 || p_provider
->cbs
.pf_update_progress
== NULL
572 || p_provider
->cbs
.pf_cancel
== NULL
)
574 vlc_mutex_unlock(&p_provider
->lock
);
579 if (vasprintf(&psz_text
, psz_fmt
, ap
) == -1)
581 vlc_mutex_unlock(&p_provider
->lock
);
585 vlc_dialog_id
*p_id
= dialog_add_locked(p_provider
, VLC_DIALOG_PROGRESS
);
589 vlc_mutex_unlock(&p_provider
->lock
);
592 p_id
->b_progress_indeterminate
= b_indeterminate
;
593 p_id
->psz_progress_text
= psz_text
;
594 p_provider
->cbs
.pf_display_progress(p_provider
->p_cbs_data
, p_id
, psz_title
,
595 psz_text
, b_indeterminate
, f_position
,
597 vlc_mutex_unlock(&p_provider
->lock
);
604 vlc_dialog_display_progress_va(vlc_object_t
*p_obj
, bool b_indeterminate
,
605 float f_position
, const char *psz_cancel
,
606 const char *psz_title
, const char *psz_fmt
,
609 assert(p_obj
!= NULL
&& psz_title
!= NULL
&& psz_fmt
!= NULL
);
611 vlc_dialog_provider
*p_provider
= get_dialog_provider(p_obj
, true);
612 if (p_provider
== NULL
)
615 int i_ret
= display_progress_va(p_provider
, &p_id
, b_indeterminate
,
616 f_position
, psz_cancel
, psz_title
, psz_fmt
,
618 return i_ret
== VLC_SUCCESS
? p_id
: NULL
;
621 #undef vlc_dialog_display_progress
623 vlc_dialog_display_progress(vlc_object_t
*p_obj
, bool b_indeterminate
,
624 float f_position
, const char *psz_cancel
,
625 const char *psz_title
, const char *psz_fmt
, ...)
627 assert(psz_fmt
!= NULL
);
629 va_start(ap
, psz_fmt
);
630 vlc_dialog_id
*p_id
=
631 vlc_dialog_display_progress_va(p_obj
, b_indeterminate
, f_position
,
632 psz_cancel
, psz_title
, psz_fmt
, ap
);
638 dialog_update_progress(vlc_object_t
*p_obj
, vlc_dialog_id
*p_id
, float f_value
,
641 assert(p_obj
!= NULL
&& p_id
!= NULL
);
642 vlc_dialog_provider
*p_provider
= get_dialog_provider(p_obj
, false);
644 vlc_mutex_lock(&p_provider
->lock
);
645 if (p_provider
->cbs
.pf_update_progress
== NULL
||
646 vlc_dialog_is_cancelled(p_obj
, p_id
))
648 vlc_mutex_unlock(&p_provider
->lock
);
653 if (p_id
->b_progress_indeterminate
)
656 if (psz_text
!= NULL
)
658 free(p_id
->psz_progress_text
);
659 p_id
->psz_progress_text
= psz_text
;
661 p_provider
->cbs
.pf_update_progress(p_provider
->p_cbs_data
, p_id
, f_value
,
662 p_id
->psz_progress_text
);
664 vlc_mutex_unlock(&p_provider
->lock
);
668 #undef vlc_dialog_update_progress
670 vlc_dialog_update_progress(vlc_object_t
*p_obj
, vlc_dialog_id
*p_id
,
673 return dialog_update_progress(p_obj
, p_id
, f_value
, NULL
);
677 vlc_dialog_update_progress_text_va(vlc_object_t
*p_obj
, vlc_dialog_id
*p_id
,
678 float f_value
, const char *psz_fmt
,
681 assert(psz_fmt
!= NULL
);
684 if (vasprintf(&psz_text
, psz_fmt
, ap
) == -1)
686 return dialog_update_progress(p_obj
, p_id
, f_value
, psz_text
);
689 #undef vlc_dialog_update_progress_text
691 vlc_dialog_update_progress_text(vlc_object_t
*p_obj
, vlc_dialog_id
*p_id
,
692 float f_value
, const char *psz_fmt
, ...)
694 assert(psz_fmt
!= NULL
);
696 va_start(ap
, psz_fmt
);
697 int i_ret
= vlc_dialog_update_progress_text_va(p_obj
, p_id
, f_value
,
703 #undef vlc_dialog_release
705 vlc_dialog_release(vlc_object_t
*p_obj
, vlc_dialog_id
*p_id
)
707 assert(p_obj
!= NULL
&& p_id
!= NULL
);
708 vlc_dialog_provider
*p_provider
= get_dialog_provider(p_obj
, false);
710 vlc_mutex_lock(&p_provider
->lock
);
711 dialog_cancel_locked(p_provider
, p_id
);
712 dialog_remove_locked(p_provider
, p_id
);
713 vlc_mutex_unlock(&p_provider
->lock
);
716 #undef vlc_dialog_is_cancelled
718 vlc_dialog_is_cancelled(vlc_object_t
*p_obj
, vlc_dialog_id
*p_id
)
721 assert(p_id
!= NULL
);
723 vlc_mutex_lock(&p_id
->lock
);
724 bool b_cancelled
= p_id
->b_cancelled
;
725 vlc_mutex_unlock(&p_id
->lock
);
730 vlc_dialog_id_set_context(vlc_dialog_id
*p_id
, void *p_context
)
732 vlc_mutex_lock(&p_id
->lock
);
733 p_id
->p_context
= p_context
;
734 vlc_mutex_unlock(&p_id
->lock
);
738 vlc_dialog_id_get_context(vlc_dialog_id
*p_id
)
740 assert(p_id
!= NULL
);
741 vlc_mutex_lock(&p_id
->lock
);
742 void *p_context
= p_id
->p_context
;
743 vlc_mutex_unlock(&p_id
->lock
);
748 dialog_id_post(vlc_dialog_id
*p_id
, struct dialog_answer
*p_answer
)
750 vlc_mutex_lock(&p_id
->lock
);
751 if (p_answer
== NULL
)
753 p_id
->b_cancelled
= true;
757 p_id
->answer
= *p_answer
;
758 p_id
->b_answered
= true;
761 if (p_id
->i_refcount
> 0)
763 vlc_cond_signal(&p_id
->wait
);
764 vlc_mutex_unlock(&p_id
->lock
);
768 vlc_mutex_unlock(&p_id
->lock
);
769 dialog_id_release(p_id
);
775 vlc_dialog_id_post_login(vlc_dialog_id
*p_id
, const char *psz_username
,
776 const char *psz_password
, bool b_store
)
778 assert(p_id
!= NULL
&& psz_username
!= NULL
&& psz_password
!= NULL
);
780 struct dialog_answer answer
= {
781 .i_type
= VLC_DIALOG_LOGIN
,
784 .psz_username
= strdup(psz_username
),
785 .psz_password
= strdup(psz_password
),
788 if (answer
.u
.login
.psz_username
== NULL
789 || answer
.u
.login
.psz_password
== NULL
)
791 free(answer
.u
.login
.psz_username
);
792 free(answer
.u
.login
.psz_password
);
793 dialog_id_post(p_id
, NULL
);
797 return dialog_id_post(p_id
, &answer
);
801 vlc_dialog_id_post_action(vlc_dialog_id
*p_id
, int i_action
)
803 assert(p_id
!= NULL
);
805 struct dialog_answer answer
= {
806 .i_type
= VLC_DIALOG_QUESTION
,
807 .u
.question
= { .i_action
= i_action
},
810 return dialog_id_post(p_id
, &answer
);
814 vlc_dialog_id_dismiss(vlc_dialog_id
*p_id
)
816 return dialog_id_post(p_id
, NULL
);
819 #undef vlc_dialog_provider_set_ext_callback
821 vlc_dialog_provider_set_ext_callback(vlc_object_t
*p_obj
,
822 vlc_dialog_ext_update_cb pf_update
,
825 assert(p_obj
!= NULL
);
826 vlc_dialog_provider
*p_provider
= get_dialog_provider(p_obj
, false);
828 vlc_mutex_lock(&p_provider
->lock
);
830 p_provider
->pf_ext_update
= pf_update
;
831 p_provider
->p_ext_data
= p_data
;
833 vlc_mutex_unlock(&p_provider
->lock
);
836 #undef vlc_ext_dialog_update
838 vlc_ext_dialog_update(vlc_object_t
*p_obj
, extension_dialog_t
*p_ext_dialog
)
840 assert(p_obj
!= NULL
);
841 vlc_dialog_provider
*p_provider
= get_dialog_provider(p_obj
, false);
843 vlc_mutex_lock(&p_provider
->lock
);
844 if (p_provider
->pf_ext_update
== NULL
)
846 vlc_mutex_unlock(&p_provider
->lock
);
849 p_provider
->pf_ext_update(p_ext_dialog
, p_provider
->p_ext_data
);
850 vlc_mutex_unlock(&p_provider
->lock
);