diff options
author | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2013-06-10 14:22:02 +0200 |
---|---|---|
committer | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2013-06-10 14:22:02 +0200 |
commit | 36a2529f8ae07fabda5a88b867307dde806a52f6 (patch) | |
tree | 098b1b8d214a5d4a5262931b4a2460ca4e6c635f | |
parent | 1f1b5114d4a94750d02a38357ecf45f72f3dd3a3 (diff) | |
download | gtk-vlc-player-36a2529f8ae07fabda5a88b867307dde806a52f6.tar.gz |
gtk-vlc-player widget: fixed VLC callback processing (dead locks)
either libVLC 2.0.5 changed the semantics of their callbacks (they can be
invoked from the main thread, i.e. from the VLC method resulting in the event);
or GTK+ 2.24 silently changed the type of the GDK mutex from recursive to simple.
in either case to avoid GDK mutex deadlocks we must check whether the VLC
callback's thread already holds the lock or owns the main context
-rw-r--r-- | lib/gtk-vlc-player/gtk-vlc-player.c | 44 |
1 files changed, 38 insertions, 6 deletions
diff --git a/lib/gtk-vlc-player/gtk-vlc-player.c b/lib/gtk-vlc-player/gtk-vlc-player.c index 03179ed..97a7115 100644 --- a/lib/gtk-vlc-player/gtk-vlc-player.c +++ b/lib/gtk-vlc-player/gtk-vlc-player.c @@ -38,6 +38,7 @@ #include <glib/gprintf.h> #include <gtk/gtk.h> +#include <gdk/gdk.h> #ifdef G_OS_WIN32 #include <gdk/gdkwin32.h> #else @@ -57,6 +58,9 @@ static void gtk_vlc_player_init(GtkVlcPlayer *klass); static void gtk_vlc_player_dispose(GObject *gobject); static void gtk_vlc_player_finalize(GObject *gobject); +static inline void maybe_lock_gdk(void); +static inline void maybe_unlock_gdk(void); + #ifdef G_OS_WIN32 static BOOL CALLBACK enumerate_vlc_windows_cb(HWND hWndvlc, LPARAM lParam); static gboolean poll_vlc_event_window_cb(gpointer data); @@ -308,6 +312,34 @@ gtk_vlc_player_finalize(GObject *gobject) G_OBJECT_CLASS(gtk_vlc_player_parent_class)->finalize(gobject); } +/** + * @brief Locks GDK mutex if necessary. + * + * When GTK+ functions are invoked from another than the main + * thread (the one with the \e gtk_main() event loop), + * \e gdk_threads_enter() must be called. + * This auxiliary function is for callers (like VLC callbacks) that + * may or may not be invoked from the main event loop to avoid dead locks. + */ +static inline void +maybe_lock_gdk(void) +{ + if (!g_main_context_is_owner(g_main_context_default())) + gdk_threads_enter(); +} + +/** + * @brief Unlocks GDK mutex if necessary. + * + * @see maybe_lock_gdk + */ +static inline void +maybe_unlock_gdk(void) +{ + if (!g_main_context_is_owner(g_main_context_default())) + gdk_threads_leave(); +} + #ifdef G_OS_WIN32 static BOOL CALLBACK @@ -478,11 +510,11 @@ vlc_time_changed(const struct libvlc_event_t *event, void *user_data) { assert(event->type == libvlc_MediaPlayerTimeChanged); - /* VLC callbacks are invoked from another thread! */ - gdk_threads_enter(); + /* VLC callbacks may be invoked from another thread! */ + maybe_lock_gdk(); update_time(GTK_VLC_PLAYER(user_data), (gint64)event->u.media_player_time_changed.new_time); - gdk_threads_leave(); + maybe_unlock_gdk(); } static void @@ -490,11 +522,11 @@ vlc_length_changed(const struct libvlc_event_t *event, void *user_data) { assert(event->type == libvlc_MediaPlayerLengthChanged); - /* VLC callbacks are invoked from another thread! */ - gdk_threads_enter(); + /* VLC callbacks may be invoked from another thread! */ + maybe_lock_gdk(); update_length(GTK_VLC_PLAYER(user_data), (gint64)event->u.media_player_length_changed.new_length); - gdk_threads_leave(); + maybe_unlock_gdk(); } static void |