Index: modules/gui/macosx/voutqt.m =================================================================== --- modules/gui/macosx/voutqt.m (revision 20403) +++ modules/gui/macosx/voutqt.m (working copy) @@ -39,6 +39,7 @@ #include "intf.h" #include "vout.h" +#include #define QT_MAX_DIRECTBUFFERS 10 #define VL_MAX_DISPLAYS 16 @@ -138,13 +139,22 @@ p_vout->pf_display = DisplayVideo; p_vout->pf_control = ControlVideo; - /* Are we embedded? If so, the drawable value will be a pointer to a + /* Are we embedded? If so, the drawable value should be a pointer to a * CGrafPtr that we're expected to use */ var_Get( p_vout->p_libvlc, "drawable", &value_drawable ); - if( value_drawable.i_int != 0 ) + if( value_drawable.i_int != 0 ) { + vlc_value_t value_drawable_type; + + var_Get( p_vout->p_libvlc, "macosx-drawable-type", &value_drawable_type ); + if( value_drawable_type.i_int != VLCDrawableCGrafPtr ) { + msg_Err( p_vout, "QT interface requires a CGrafPtr when embedded" ); + return( 1 ); + } + p_vout->p_sys->b_embedded = VLC_TRUE; - else + } else { p_vout->p_sys->b_embedded = VLC_FALSE; + } p_vout->p_sys->b_cpu_has_simd = vlc_CPU() & (CPU_CAPABILITY_ALTIVEC|CPU_CAPABILITY_MMXEXT); Index: modules/gui/macosx/voutgl.m =================================================================== --- modules/gui/macosx/voutgl.m (revision 20403) +++ modules/gui/macosx/voutgl.m (working copy) @@ -35,6 +35,7 @@ #include /* strerror() */ #include +#include #include "intf.h" #include "vout.h" @@ -43,6 +44,7 @@ #include #include +#include /***************************************************************************** * VLCGLView interface @@ -67,13 +69,18 @@ /* Mozilla plugin-related variables */ vlc_bool_t b_embedded; AGLContext agl_ctx; - AGLDrawable agl_drawable; int i_offx, i_offy; int i_width, i_height; WindowRef theWindow; WindowGroupRef winGroup; vlc_bool_t b_clipped_out; - Rect clipBounds, viewBounds; + Rect clipBounds, viewBounds; + + libvlc_macosx_drawable_type_t drawable_type; + union { + CGrafPtr CGrafPtr; + ControlRef ControlRef; + } drawable; }; /***************************************************************************** @@ -462,17 +469,90 @@ static void aglReshape( vout_thread_t * p_vout ); static OSStatus WindowEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData); -static int aglInit( vout_thread_t * p_vout ) +/* returns the bounds of the drawable control/window */ +static Rect aglGetBounds( vout_thread_t * p_vout ) { + WindowRef win; + Rect rect; + + switch( p_vout->p_sys->drawable_type ) { + case VLCDrawableCGrafPtr: + win = GetWindowFromPort( p_vout->p_sys->drawable.CGrafPtr ); + GetWindowPortBounds( win, &rect ); + break; + + case VLCDrawableControlRef: + win = GetControlOwner( p_vout->p_sys->drawable.ControlRef ); + GetControlBounds( p_vout->p_sys->drawable.ControlRef, &rect ); + break; + } + + return rect; +} + +/* returns the window containing the drawable area */ +static WindowRef aglGetWindow( vout_thread_t * p_vout ) +{ + WindowRef window; + + switch( p_vout->p_sys->drawable_type ) { + case VLCDrawableCGrafPtr: + window = GetWindowFromPort( p_vout->p_sys->drawable.CGrafPtr ); + break; + + case VLCDrawableControlRef: + window = GetControlOwner( p_vout->p_sys->drawable.ControlRef ); + break; + } + + return window; +} + +/* gets the graphics port associated with our drawing area */ +static CGrafPtr aglGetPort( vout_thread_t * p_vout ) +{ + CGrafPtr port; + + switch( p_vout->p_sys->drawable_type ) { + case VLCDrawableCGrafPtr: + port = p_vout->p_sys->drawable.CGrafPtr; + break; + + case VLCDrawableControlRef: + port = GetWindowPort( GetControlOwner( + p_vout->p_sys->drawable.ControlRef + ) ); + break; + } + + return port; +} + +/* (re)process "drawable-*" and "macosx-drawable-type" variables. `drawable' is a + parameter to allow it to be overridden (REPARENT) */ +static int aglProcessDrawable( vout_thread_t * p_vout, libvlc_drawable_t drawable ) +{ vlc_value_t val; + vlc_value_t val_type; + AGLDrawable agl_drawable; + Rect clipBounds,viewBounds; - Rect viewBounds; - Rect clipBounds; - - var_Get( p_vout->p_libvlc, "drawable", &val ); - p_vout->p_sys->agl_drawable = (AGLDrawable)val.i_int; - aglSetDrawable(p_vout->p_sys->agl_ctx, p_vout->p_sys->agl_drawable); + var_Get( p_vout->p_libvlc, "macosx-drawable-type", &val_type ); + p_vout->p_sys->drawable_type = val_type.i_int; + switch( val_type.i_int ) { + case VLCDrawableCGrafPtr: + p_vout->p_sys->drawable.CGrafPtr = (CGrafPtr)drawable; + break; + + case VLCDrawableControlRef: + p_vout->p_sys->drawable.ControlRef = (ControlRef)drawable; + break; + } + + agl_drawable = (AGLDrawable)aglGetPort( p_vout ); + aglSetDrawable(p_vout->p_sys->agl_ctx, agl_drawable); + var_Get( p_vout->p_libvlc, "drawable-view-top", &val ); viewBounds.top = val.i_int; var_Get( p_vout->p_libvlc, "drawable-view-left", &val ); @@ -481,15 +561,21 @@ viewBounds.bottom = val.i_int; var_Get( p_vout->p_libvlc, "drawable-view-right", &val ); viewBounds.right = val.i_int; - var_Get( p_vout->p_libvlc, "drawable-clip-top", &val ); - clipBounds.top = val.i_int; - var_Get( p_vout->p_libvlc, "drawable-clip-left", &val ); - clipBounds.left = val.i_int; - var_Get( p_vout->p_libvlc, "drawable-clip-bottom", &val ); - clipBounds.bottom = val.i_int; - var_Get( p_vout->p_libvlc, "drawable-clip-right", &val ); - clipBounds.right = val.i_int; + if( !viewBounds.top && !viewBounds.left && !viewBounds.right && !viewBounds.bottom ) { + /* view bounds not set, use control/window bounds */ + clipBounds = viewBounds = aglGetBounds( p_vout ); + } else { + var_Get( p_vout->p_libvlc, "drawable-clip-top", &val ); + clipBounds.top = val.i_int; + var_Get( p_vout->p_libvlc, "drawable-clip-left", &val ); + clipBounds.left = val.i_int; + var_Get( p_vout->p_libvlc, "drawable-clip-bottom", &val ); + clipBounds.bottom = val.i_int; + var_Get( p_vout->p_libvlc, "drawable-clip-right", &val ); + clipBounds.right = val.i_int; + } + p_vout->p_sys->b_clipped_out = (clipBounds.top == clipBounds.bottom) || (clipBounds.left == clipBounds.right); if( ! p_vout->p_sys->b_clipped_out ) @@ -501,7 +587,15 @@ } p_vout->p_sys->clipBounds = clipBounds; p_vout->p_sys->viewBounds = viewBounds; +} +static int aglInit( vout_thread_t * p_vout ) +{ + vlc_value_t val; + + var_Get( p_vout->p_libvlc, "drawable", &val ); + aglProcessDrawable( p_vout, val.i_int ); + return VLC_SUCCESS; } @@ -564,6 +658,26 @@ static int aglManage( vout_thread_t * p_vout ) { + if( p_vout->p_sys->drawable_type == VLCDrawableControlRef ) { + /* auto-detect size changes in the control by polling */ + Rect clipBounds, viewBounds; + + clipBounds = viewBounds = aglGetBounds( p_vout ); + + if( memcmp(&clipBounds, &(p_vout->p_sys->clipBounds), sizeof(clipBounds) ) + && memcmp(&viewBounds, &(p_vout->p_sys->viewBounds), sizeof(viewBounds)) ) + { + /* size has changed since last poll */ + + p_vout->p_sys->clipBounds = clipBounds; + p_vout->p_sys->viewBounds = viewBounds; + aglLock( p_vout ); + aglSetViewport(p_vout, viewBounds, clipBounds); + aglReshape( p_vout ); + aglUnlock( p_vout ); + } + } + if( p_vout->i_changes & VOUT_ASPECT_CHANGE ) { aglLock( p_vout ); @@ -586,42 +700,28 @@ { /* Close the fullscreen window and resume normal drawing */ vlc_value_t val; - Rect viewBounds; - Rect clipBounds; var_Get( p_vout->p_libvlc, "drawable", &val ); - p_vout->p_sys->agl_drawable = (AGLDrawable)val.i_int; - aglSetDrawable(p_vout->p_sys->agl_ctx, p_vout->p_sys->agl_drawable); + aglProcessDrawable( p_vout, val.i_int ); - var_Get( p_vout->p_libvlc, "drawable-view-top", &val ); - viewBounds.top = val.i_int; - var_Get( p_vout->p_libvlc, "drawable-view-left", &val ); - viewBounds.left = val.i_int; - var_Get( p_vout->p_libvlc, "drawable-view-bottom", &val ); - viewBounds.bottom = val.i_int; - var_Get( p_vout->p_libvlc, "drawable-view-right", &val ); - viewBounds.right = val.i_int; - var_Get( p_vout->p_libvlc, "drawable-clip-top", &val ); - clipBounds.top = val.i_int; - var_Get( p_vout->p_libvlc, "drawable-clip-left", &val ); - clipBounds.left = val.i_int; - var_Get( p_vout->p_libvlc, "drawable-clip-bottom", &val ); - clipBounds.bottom = val.i_int; - var_Get( p_vout->p_libvlc, "drawable-clip-right", &val ); - clipBounds.right = val.i_int; + /*the following was here, superfluous due to the same in aglLock? + aglSetCurrentContext(p_vout->p_sys->agl_ctx);*/ - aglSetCurrentContext(p_vout->p_sys->agl_ctx); - aglSetViewport(p_vout, viewBounds, clipBounds); - /* Most Carbon APIs are not thread-safe, therefore delagate some GUI visibilty update to the main thread */ sendEventToMainThread(GetWindowEventTarget(p_vout->p_sys->theWindow), kEventClassVLCPlugin, kEventVLCPluginHideFullscreen); } else { + CGDirectDisplayID displayID; + CGRect displayBounds; Rect deviceRect; - GDHandle deviceHdl = GetMainDevice(); - deviceRect = (*deviceHdl)->gdRect; + /* the main display has its origin at (0,0) */ + displayBounds = CGDisplayBounds( CGMainDisplayID() ); + deviceRect.left = 0; + deviceRect.top = 0; + deviceRect.right = displayBounds.size.width; + deviceRect.bottom = displayBounds.size.height; if( !p_vout->p_sys->theWindow ) { @@ -669,8 +769,9 @@ SetWindowBounds(p_vout->p_sys->theWindow, kWindowContentRgn, &deviceRect); } glClear( GL_COLOR_BUFFER_BIT ); - p_vout->p_sys->agl_drawable = (AGLDrawable)GetWindowPort(p_vout->p_sys->theWindow); - aglSetDrawable(p_vout->p_sys->agl_ctx, p_vout->p_sys->agl_drawable); + p_vout->p_sys->drawable_type = VLCDrawableCGrafPtr; + p_vout->p_sys->drawable.CGrafPtr = GetWindowPort(p_vout->p_sys->theWindow); + aglSetDrawable(p_vout->p_sys->agl_ctx, p_vout->p_sys->drawable.CGrafPtr); aglSetCurrentContext(p_vout->p_sys->agl_ctx); aglSetViewport(p_vout, deviceRect, deviceRect); //aglSetFullScreen(p_vout->p_sys->agl_ctx, device_width, device_height, 0, 0); @@ -753,11 +854,10 @@ case VOUT_REPARENT: { - AGLDrawable drawable = (AGLDrawable)va_arg( args, int); - if( !p_vout->b_fullscreen && drawable != p_vout->p_sys->agl_drawable ) + libvlc_drawable_t drawable = (libvlc_drawable_t)va_arg( args, int); + if( !p_vout->b_fullscreen ) { - p_vout->p_sys->agl_drawable = drawable; - aglSetDrawable(p_vout->p_sys->agl_ctx, drawable); + aglProcessDrawable( p_vout, drawable ); } return VLC_SUCCESS; } @@ -771,8 +871,16 @@ { if( ! p_vout->p_sys->b_clipped_out ) { + WindowRef win; + Rect rect; + p_vout->p_sys->b_got_frame = VLC_TRUE; aglSwapBuffers(p_vout->p_sys->agl_ctx); + + win = aglGetWindow( p_vout ); + rect = aglGetBounds( p_vout ); + + InvalWindowRect( win, &rect ); } else { @@ -788,12 +896,14 @@ // however AGL coordinates are based on window structure region // and are vertically flipped GLint rect[4]; - CGrafPtr port = (CGrafPtr)p_vout->p_sys->agl_drawable; + WindowRef window; Rect winBounds, clientBounds; - GetWindowBounds(GetWindowFromPort(port), + window = aglGetWindow( p_vout ); + + GetWindowBounds(window, kWindowStructureRgn, &winBounds); - GetWindowBounds(GetWindowFromPort(port), + GetWindowBounds(window, kWindowContentRgn, &clientBounds); /* update video clipping bounds in drawable */ Index: bindings/python/vlc_instance.c =================================================================== --- bindings/python/vlc_instance.c (revision 20403) +++ bindings/python/vlc_instance.c (working copy) @@ -349,6 +349,30 @@ } static PyObject * +vlcInstance_video_set_macosx_parent_type( PyObject *self, PyObject *args ) +{ + libvlc_exception_t ex; + int i_drawable_type; + + if( !PyArg_ParseTuple( args, "i", &i_drawable_type ) ) + return NULL; + + if( i_drawable_type != VLCDrawableCGrafPtr + && i_drawable_type != VLCDrawableControlRef ) + { + PyErr_SetString( vlcInstance_Exception, "Invalid drawable type." ); + return NULL; + } + + LIBVLC_TRY; + libvlc_video_set_macosx_parent_type( LIBVLC_INSTANCE->p_instance, (libvlc_macosx_drawable_type_t) i_drawable_type, &ex ); + LIBVLC_EXCEPT; + + Py_INCREF( Py_None ); + return Py_None; +} + +static PyObject * vlcInstance_video_set_size( PyObject *self, PyObject *args ) { libvlc_exception_t ex; @@ -733,6 +757,8 @@ "playlist_get_input() -> object Return the current input"}, { "video_set_parent", vlcInstance_video_set_parent, METH_VARARGS, "video_set_parent(xid=int) Set the parent xid or HWND"}, + { "video_set_macosx_parent_type", vlcInstance_video_set_macosx_parent_type, METH_VARARGS, + "video_set_macosx_parent_type(drawabletype=int) Set the type of parent used on Mac OS/X (see the Drawable* constants)"}, { "video_set_size", vlcInstance_video_set_size, METH_VARARGS, "video_set_size(width=int, height=int) Set the video width and height"}, { "audio_toggle_mute", vlcInstance_audio_toggle_mute, METH_VARARGS, Index: bindings/python/vlc_module.c =================================================================== --- bindings/python/vlc_module.c (revision 20403) +++ bindings/python/vlc_module.c (working copy) @@ -147,6 +147,10 @@ mediacontrol_EndStatus ); PyModule_AddIntConstant( p_module, "UndefinedStatus", mediacontrol_UndefinedStatus ); + PyModule_AddIntConstant( p_module, "DrawableCGrafPtr", + VLCDrawableCGrafPtr ); + PyModule_AddIntConstant( p_module, "DrawableControlRef", + VLCDrawableControlRef ); } Index: src/control/video.c =================================================================== --- src/control/video.c (revision 20403) +++ src/control/video.c (working copy) @@ -277,6 +277,21 @@ /* global video settings */ +void libvlc_video_set_macosx_parent_type( libvlc_instance_t *p_instance, libvlc_macosx_drawable_type_t t, + libvlc_exception_t *p_e ) +{ + var_SetInteger(p_instance->p_libvlc_int, "macosx-drawable-type", (int)t); +} + +libvlc_macosx_drawable_type_t libvlc_video_get_macosx_parent_type( libvlc_instance_t *p_instance, libvlc_exception_t *p_e ) +{ + libvlc_macosx_drawable_type_t result; + + result = var_GetInteger( p_instance->p_libvlc_int, "macosx-drawable-type" ); + + return result; +} + void libvlc_video_set_parent( libvlc_instance_t *p_instance, libvlc_drawable_t d, libvlc_exception_t *p_e ) { Index: src/libvlc-common.c =================================================================== --- src/libvlc-common.c (revision 20403) +++ src/libvlc-common.c (working copy) @@ -941,6 +941,10 @@ var_Create( p_libvlc, "drawable-clip-bottom", VLC_VAR_INTEGER ); var_Create( p_libvlc, "drawable-clip-right", VLC_VAR_INTEGER ); +#ifdef __APPLE__ + var_Create( p_libvlc, "macosx-drawable-type", VLC_VAR_INTEGER ); +#endif + /* Create volume callback system. */ var_Create( p_libvlc, "volume-change", VLC_VAR_BOOL ); Index: include/vlc/libvlc.h =================================================================== --- include/vlc/libvlc.h (revision 20403) +++ include/vlc/libvlc.h (working copy) @@ -424,6 +424,10 @@ */ VLC_PUBLIC_API void libvlc_video_redraw_rectangle( libvlc_input_t *, const libvlc_rectangle_t *, libvlc_exception_t * ); +VLC_PUBLIC_API void libvlc_video_set_macosx_parent_type( libvlc_instance_t *, libvlc_macosx_drawable_type_t, libvlc_exception_t * ); + +VLC_PUBLIC_API libvlc_macosx_drawable_type_t libvlc_video_get_macosx_parent_type( libvlc_instance_t *, libvlc_exception_t * ); + /** * Set the default video output parent * this settings will be used as default for all video outputs Index: include/vlc/libvlc_structures.h =================================================================== --- include/vlc/libvlc_structures.h (revision 20403) +++ include/vlc/libvlc_structures.h (working copy) @@ -83,12 +83,22 @@ /** * Downcast to this general type as placeholder for a platform specific one, such as: * Drawable on X11, -* CGrafPort on MacOSX, +* (libvlc_macosx_drawable_type_t) on MacOSX, * HWND on win32 */ typedef int libvlc_drawable_t; /** +* Type of libvlc_drawable_t on MaxOSX. Available types: +* - VLCDrawableCGrafPtr +* - VLCDrawableControlRef +*/ +typedef enum { + VLCDrawableCGrafPtr = 0, + VLCDrawableControlRef, +} libvlc_macosx_drawable_type_t; + +/** * Rectangle type for video geometry */ typedef struct