[vlc-devel] commit: Drawable: check properly for busy drawable ( Rémi Denis-Courmont )
git version control
git at videolan.org
Sat May 23 15:55:00 CEST 2009
vlc | branch: 1.0-bugfix | Rémi Denis-Courmont <remi at remlab.net> | Sat May 23 16:50:32 2009 +0300| [0577234ca3dbfe9a3d9ea5eb82d533bedf88469c] | committer: Rémi Denis-Courmont
Drawable: check properly for busy drawable
(see http://forum.videolan.org/viewtopic.php?f=32&t=59426)
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=0577234ca3dbfe9a3d9ea5eb82d533bedf88469c
---
modules/video_output/drawable.c | 102 +++++++++++++++++++++++++++-----------
1 files changed, 72 insertions(+), 30 deletions(-)
diff --git a/modules/video_output/drawable.c b/modules/video_output/drawable.c
index b041ada..f97b30d 100644
--- a/modules/video_output/drawable.c
+++ b/modules/video_output/drawable.c
@@ -64,59 +64,80 @@ vlc_module_end ()
static int Control (vout_window_t *, int, va_list);
+/* TODO: move to vlc_variables.h */
+static inline void *var_GetAddress (vlc_object_t *o, const char *name)
+{
+ vlc_value_t val;
+ return var_Get (o, name, &val) ? NULL : val.p_address;
+}
+
+static vlc_mutex_t serializer = VLC_STATIC_MUTEX;
+
/**
* Find the drawable set by libvlc application.
*/
static int Open (vlc_object_t *obj, const char *varname, bool ptr)
{
- static vlc_mutex_t serializer = VLC_STATIC_MUTEX;
vout_window_t *wnd = (vout_window_t *)obj;
- vlc_value_t val, globval;
+ void **used, *val;
+ size_t n = 0;
- if (var_Create (obj->p_libvlc, "drawable-busy", VLC_VAR_BOOL)
+ if (var_Create (obj->p_libvlc, "drawables-in-use", VLC_VAR_ADDRESS)
|| var_Create (obj, varname, VLC_VAR_DOINHERIT
| (ptr ? VLC_VAR_ADDRESS : VLC_VAR_INTEGER)))
return VLC_ENOMEM;
- var_Get (obj, varname, &val);
+ if (ptr)
+ val = var_GetAddress (obj, varname);
+ else
+ val = (void *)(uintptr_t)var_GetInteger (obj, varname);
+ var_Destroy (obj, varname);
+ msg_Err (wnd, "%zu, %p", n, val);
+
+ /* Keep a list of busy drawables, so we don't overlap videos if there are
+ * more than one video track in the stream. */
vlc_mutex_lock (&serializer);
- /* Note: We cannot simply clear the drawable variable.
- * It would break libvlc_video_get_parent(). */
- var_Get (obj->p_libvlc, varname, &globval);
- if (ptr ? (val.p_address == globval.p_address)
- : (val.i_int == globval.i_int))
+ /* TODO: per-type list of busy drawables */
+ used = var_GetAddress (VLC_OBJECT (obj->p_libvlc), "drawables-in-use");
+ if (used != NULL)
{
- if (var_GetBool (obj->p_libvlc, "drawable-busy"))
- { /* LibVLC-wide drawable already in use */
- if (ptr)
- val.p_address = NULL;
- else
- val.i_int = 0;
+ while (used[n] != NULL)
+ {
+ if (used[n] == val)
+ goto skip;
+ n++;
}
- else
- var_SetBool (obj->p_libvlc, "drawable-busy", true);
}
- /* If we got a drawable _not_ from the root object (from the input?),
- * We assume it is not busy. This is a bug. */
- vlc_mutex_unlock (&serializer);
-
- var_Destroy (obj, varname);
- if (ptr ? (val.p_address == NULL) : (val.i_int == 0))
+ used = realloc (used, sizeof (*used) * (n + 2));
+ if (used != NULL)
{
- var_Destroy (obj->p_libvlc, "drawable-busy");
- return VLC_EGENERIC;
+ used[n] = val;
+ used[n + 1] = NULL;
+ var_SetAddress (obj->p_libvlc, "drawables-in-use", used);
}
+ else
+ {
+skip:
+ msg_Warn (wnd, "drawable %p is busy", val);
+ val = NULL;
+ }
+ vlc_mutex_unlock (&serializer);
+ msg_Err (wnd, "%zu, %p", n, val);
+
+ if (val == NULL)
+ return VLC_EGENERIC;
if (ptr)
- wnd->handle.hwnd = val.p_address;
+ wnd->handle.hwnd = val;
else
- wnd->handle.xid = val.i_int;
+ wnd->handle.xid = (uintptr_t)val;
/* FIXME: check that X server matches --x11-display (if specified) */
/* FIXME: get window size (in platform-dependent ways) */
wnd->control = Control;
+ wnd->p_sys = val;
return VLC_SUCCESS;
}
@@ -136,11 +157,32 @@ static int OpenHWND (vlc_object_t *obj)
*/
static void Close (vlc_object_t *obj)
{
- /* This is atomic with regards to var_GetBool() in Open(): */
- var_SetBool (obj->p_libvlc, "drawable-busy", false);
+ vout_window_t *wnd = (vout_window_t *)obj;
+ void **used, *val = wnd->p_sys;
+ size_t n = 0;
+
+ /* Remove this drawable from the list of busy ones */
+ vlc_mutex_lock (&serializer);
+ used = var_GetAddress (VLC_OBJECT (obj->p_libvlc), "drawables-in-use");
+ assert (used);
+ while (used[n] != val)
+ {
+ assert (used[n]);
+ n++;
+ }
+ do
+ used[n] = used[n + 1];
+ while (used[n + 1] != NULL);
+
+ if (n == 0)
+ /* should not be needed (var_Destroy...) but better safe than sorry: */
+ var_SetAddress (obj->p_libvlc, "drawables-in-use", NULL);
+ vlc_mutex_unlock (&serializer);
+ if (n == 0)
+ free (used);
/* Variables are reference-counted... */
- var_Destroy (obj->p_libvlc, "drawable-busy");
+ var_Destroy (obj->p_libvlc, "drawables-in-use");
}
More information about the vlc-devel
mailing list