From: RĂ©mi Denis-Courmont Date: Mon, 20 Oct 2008 18:23:59 +0000 (+0300) Subject: Do not use thread cancellation for Qt4 - fix #2225 and #2226 X-Git-Tag: 1.0.0-pre1~2399 X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=c80004131574e67fe572bd930f1c8691be691967;p=vlc Do not use thread cancellation for Qt4 - fix #2225 and #2226 --- diff --git a/modules/gui/qt4/qt4.cpp b/modules/gui/qt4/qt4.cpp index 1a2b22eada..8d26754a7d 100755 --- a/modules/gui/qt4/qt4.cpp +++ b/modules/gui/qt4/qt4.cpp @@ -65,7 +65,7 @@ static int OpenDialogs ( vlc_object_t * ); static int WindowOpen ( vlc_object_t * ); static void WindowClose ( vlc_object_t * ); static void Run ( intf_thread_t * ); -static void *Init ( vlc_object_t * ); +static void *Thread ( void * ); static void ShowDialog ( intf_thread_t *, int, int, intf_dialog_args_t * ); /***************************************************************************** @@ -232,12 +232,19 @@ vlc_module_begin(); #endif vlc_module_end(); +static struct +{ + QMutex lock; + QWaitCondition ready; +} iface; + /***************************************************************************** * Module callbacks *****************************************************************************/ static int Open( vlc_object_t *p_this ) { intf_thread_t *p_intf = (intf_thread_t *)p_this; + intf_sys_t *p_sys; #if defined Q_WS_X11 && defined HAVE_X11_XLIB_H /* Thanks for libqt4 calling exit() in QApplication::QApplication() @@ -252,36 +259,47 @@ static int Open( vlc_object_t *p_this ) #endif /* Allocations */ - p_intf->p_sys = (intf_sys_t *)malloc( sizeof( intf_sys_t ) ); - if( !p_intf->p_sys ) + p_sys = p_intf->p_sys = new intf_sys_t; + p_sys->b_isDialogProvider = false; + p_sys->p_video = NULL; /* ??? */ + p_sys->p_popup_menu = NULL; /* ??? */ + p_sys->p_playlist = pl_Hold( p_intf ); + p_sys->p_mi = NULL; + + if (vlc_clone (&p_sys->thread, Thread, p_intf, VLC_THREAD_PRIORITY_LOW)) + { + pl_Release (p_sys->p_playlist); + delete p_sys; return VLC_ENOMEM; - memset( p_intf->p_sys, 0, sizeof( intf_sys_t ) ); - - p_intf->pf_run = Run; - p_intf->p_sys->p_mi = NULL; - - /* Access to the playlist */ - p_intf->p_sys->p_playlist = pl_Hold( p_intf ); - /* one settings to rule them all */ + } + else + { + QMutexLocker locker (&iface.lock); - var_Create( p_this, "window_widget", VLC_VAR_ADDRESS ); + while (p_sys->p_mi == NULL) + iface.ready.wait (&iface.lock); + } return VLC_SUCCESS; } static int OpenDialogs( vlc_object_t *p_this ) { intf_thread_t *p_intf = (intf_thread_t *)p_this; + p_intf->pf_show_dialog = ShowDialog; + int val = Open( p_this ); if( val ) return val; - p_intf->pf_show_dialog = ShowDialog; return VLC_SUCCESS; } static void Close( vlc_object_t *p_this ) { intf_thread_t *p_intf = (intf_thread_t *)p_this; + intf_sys_t *p_sys = p_intf->p_sys; + + QApplication::postEvent (p_sys->p_mi, new QCloseEvent()); if( p_intf->p_sys->b_isDialogProvider ) { @@ -294,48 +312,25 @@ static void Close( vlc_object_t *p_this ) vlc_thread_join( p_intf ); } - vlc_object_release( p_intf->p_sys->p_playlist ); - free( p_intf->p_sys ); + vlc_join (p_sys->thread, NULL); + pl_Release (p_this); + delete p_sys; } -/***************************************************************************** - * Initialize the interface or the dialogs provider - *****************************************************************************/ -static void Run( intf_thread_t *p_intf ) -{ - if( p_intf->pf_show_dialog ) - { - if( vlc_thread_create( p_intf, "Qt dialogs", Init, 0, true ) ) - msg_Err( p_intf, "failed to create Qt dialogs thread" ); - } - else - { - Init( VLC_OBJECT(p_intf) ); - } -} static QMutex windowLock; static QWaitCondition windowWait; -static void ThreadCleanup( void *param) -{ - intf_thread_t *p_intf = (intf_thread_t *)param; - QCloseEvent *event = new QCloseEvent(); - QApplication::postEvent( p_intf->p_sys->p_mi, event ); -} - -static void *Init( vlc_object_t *obj ) +static void *Thread( void *obj ) { intf_thread_t *p_intf = (intf_thread_t *)obj; + MainInterface *p_mi; vlc_value_t val; char dummy[] = ""; char *argv[] = { dummy }; int argc = 1; - int canc = vlc_savecancel (); - msg_Dbg( p_intf, "Setting ThreadCleanup"); - vlc_cleanup_push( ThreadCleanup, (void*)p_intf ); Q_INIT_RESOURCE( vlc ); #if !defined(WIN32) && !defined(__APPLE__) @@ -370,8 +365,6 @@ static void *Init( vlc_object_t *obj ) /* Initialize timers and the Dialog Provider */ DialogsProvider::getInstance( p_intf ); - QPointer *miP = NULL; - #ifdef UPDATE_CHECK /* Checking for VLC updates */ if( config_GetInt( p_intf, "qt-updates-notif" ) && @@ -391,21 +384,19 @@ static void *Init( vlc_object_t *obj ) /* Create the normal interface in non-DP mode */ if( !p_intf->pf_show_dialog ) { - p_intf->p_sys->p_mi = new MainInterface( p_intf ); + p_mi = new MainInterface( p_intf ); /* We don't show it because it is done in the MainInterface constructor p_mi->show(); */ - p_intf->p_sys->b_isDialogProvider = false; - miP = new QPointer (p_intf->p_sys->p_mi); - val.p_address = miP; - QMutexLocker locker (&windowLock); - var_Set (p_intf, "window_widget", val); - windowWait.wakeAll (); + QMutexLocker locker (&iface.lock); + p_intf->p_sys->p_mi = p_mi; + iface.ready.wakeAll (); } else { vlc_thread_ready( p_intf ); p_intf->p_sys->b_isDialogProvider = true; + p_mi = NULL; } /* Explain to the core how to show a dialog :D */ @@ -446,31 +437,30 @@ static void *Init( vlc_object_t *obj ) p_intf->p_sys->psz_filepath = EMPTY_STR( psz_path ) ? config_GetHomeDir() : psz_path; - vlc_restorecancel (canc); /* Launch */ app->exec(); /* And quit */ - canc = vlc_savecancel (); msg_Dbg( p_intf, "Quitting the Qt4 Interface" ); - if (miP) + if (p_mi != NULL) { - QMutexLocker locker (&windowLock); + msg_Err(p_intf, "locking"); + QMutexLocker locker (&iface.lock); + p_intf->p_sys->p_mi = NULL; /* We need to warn to detach from any vout before * deleting miP (WindowClose will not be called after it) */ - p_intf->p_sys->p_mi->releaseVideo( NULL ); - - val.p_address = NULL; - var_Set (p_intf, "window_widget", val); - delete miP; + msg_Err(p_intf, "releasing"); + p_mi->releaseVideo( NULL ); + + /* Destroy first the main interface because it is connected to some + slots in the MainInputManager */ + /* Destroy under the iface lock to sync vout QPointer */ + msg_Err(p_intf, "destroying"); + delete p_mi; } - /* Destroy first the main interface because it is connected to some slots - in the MainInputManager */ - delete p_intf->p_sys->p_mi; - /* Destroy all remaining windows, because some are connected to some slots in the MainInputManager @@ -493,8 +483,6 @@ static void *Init( vlc_object_t *obj ) /* Save the path */ config_PutPsz( p_intf, "qt-filedialog-path", p_intf->p_sys->psz_filepath ); free( psz_path ); - vlc_restorecancel (canc); - vlc_cleanup_pop(); return NULL; } @@ -531,6 +519,7 @@ static int WindowControl (vout_window_t *, int, va_list); static int WindowOpen (vlc_object_t *obj) { vout_window_t *wnd = (vout_window_t *)obj; + QPointer *miP; if (config_GetInt (obj, "embedded-video") <= 0) return VLC_EGENERIC; @@ -541,23 +530,14 @@ static int WindowOpen (vlc_object_t *obj) return VLC_EGENERIC; /* Qt4 not in use */ assert (intf->i_object_type == VLC_OBJECT_INTF); - var_Create (intf, "window_widget", VLC_VAR_ADDRESS); - - vlc_value_t ptrval; - - windowLock.lock (); + QMutexLocker (&iface.lock); msg_Dbg (obj, "waiting for interface..."); - for (;;) - { - var_Get (intf, "window_widget", &ptrval); - if (ptrval.p_address != NULL) - break; - windowWait.wait (&windowLock); - } + while (intf->p_sys->p_mi == NULL) + iface.ready.wait (&iface.lock); msg_Dbg (obj, "requesting window..."); - QPointer *miP = (QPointer *)ptrval.p_address; - miP = new QPointer (*miP); /* create our own copy */ + /* create our own copy */ + miP = new QPointer (intf->p_sys->p_mi); vlc_object_release (intf); if (miP->isNull ()) @@ -565,8 +545,6 @@ static int WindowOpen (vlc_object_t *obj) wnd->handle = (*miP)->requestVideo (wnd->vout, &wnd->pos_x, &wnd->pos_y, &wnd->width, &wnd->height); - windowLock.unlock (); - if (!wnd->handle) return VLC_EGENERIC; @@ -577,8 +555,8 @@ static int WindowOpen (vlc_object_t *obj) static int WindowControl (vout_window_t *wnd, int query, va_list args) { + QMutexLocker locker (&iface.lock); QPointer *miP = (QPointer *)wnd->p_private; - QMutexLocker locker (&windowLock); if (miP->isNull ()) return VLC_EGENERIC; @@ -588,8 +566,8 @@ static int WindowControl (vout_window_t *wnd, int query, va_list args) static void WindowClose (vlc_object_t *obj) { vout_window_t *wnd = (vout_window_t *)obj; + QMutexLocker locker (&iface.lock); QPointer *miP = (QPointer *)wnd->p_private; - QMutexLocker locker (&windowLock); if (!miP->isNull ()) (*miP)->releaseVideo( wnd->handle ); diff --git a/modules/gui/qt4/qt4.hpp b/modules/gui/qt4/qt4.hpp index 38b8f3a338..a429b968b9 100755 --- a/modules/gui/qt4/qt4.hpp +++ b/modules/gui/qt4/qt4.hpp @@ -65,6 +65,7 @@ class QSettings; struct intf_sys_t { + vlc_thread_t thread; QApplication *p_app; MainInterface *p_mi;