]> git.sesse.net Git - vlc/blobdiff - modules/gui/macosx/voutqt.m
Removes trailing spaces. Removes tabs.
[vlc] / modules / gui / macosx / voutqt.m
index 70fd8f8c9acafc4606cf626ce6a20f23cc66dcb8..fcbd6785300d5427a486878d095c4070585c1f43 100644 (file)
@@ -2,7 +2,7 @@
  * vout.m: MacOS X video output module
  *****************************************************************************
  * Copyright (C) 2001-2004 the VideoLAN team
- * $Id: vout.m 8351 2004-08-02 13:06:38Z hartman $
+ * $Id$
  *
  * Authors: Colin Delacroix <colin@zoy.org>
  *          Florian G. Pflug <fgp@phlo.org>
@@ -15,7 +15,7 @@
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
- * 
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 /*****************************************************************************
  * VLCView interface
  *****************************************************************************/
-@interface VLCQTView : NSQuickDrawView
+@interface VLCQTView : NSQuickDrawView <VLCVoutViewResetting>
 {
     vout_thread_t * p_vout;
 }
 
++ (void)resetVout: (vout_thread_t *)p_vout;
 - (id) initWithVout:(vout_thread_t *)p_vout;
-
 @end
 
 struct vout_sys_t
@@ -62,7 +62,7 @@ struct vout_sys_t
     VLCVoutView       * o_vout_view;
 
     vlc_bool_t  b_saved_frame;
-    vlc_bool_t  b_altivec;
+    vlc_bool_t  b_cpu_has_simd; /* does CPU supports Altivec, MMX, etc... */
     NSRect      s_frame;
 
     CodecType i_codec;
@@ -72,10 +72,12 @@ struct vout_sys_t
     DecompressorComponent img_dc;
     ImageDescriptionHandle h_img_descr;
 
+    /* video geometry in port */
+    int i_origx, i_origy;
+    int i_width, i_height;
     /* Mozilla plugin-related variables */
     vlc_bool_t b_embedded;
-    Rect clipping_rect;
-    int portx, porty;
+    RgnHandle clip_mask;
 };
 
 struct picture_sys_t
@@ -98,6 +100,9 @@ static void DisplayVideo        ( vout_thread_t *, picture_t * );
 static int  ControlVideo        ( vout_thread_t *, int, va_list );
 
 static int CoToggleFullscreen( vout_thread_t *p_vout );
+static int DrawableRedraw( vlc_object_t *p_this, const char *psz_name,
+    vlc_value_t oval, vlc_value_t nval, void *param);
+static void UpdateEmbeddedGeometry( vout_thread_t *p_vout );
 static void QTScaleMatrix       ( vout_thread_t * );
 static int  QTCreateSequence    ( vout_thread_t * );
 static void QTDestroySequence   ( vout_thread_t * );
@@ -135,17 +140,18 @@ int E_(OpenVideoQT) ( vlc_object_t *p_this )
 
     /* Are we embedded?  If so, the drawable value will be a pointer to a
      * CGrafPtr that we're expected to use */
-    var_Get( p_vout->p_vlc, "drawable", &value_drawable );
+    var_Get( p_vout->p_libvlc, "drawable", &value_drawable );
     if( value_drawable.i_int != 0 )
         p_vout->p_sys->b_embedded = VLC_TRUE;
     else
         p_vout->p_sys->b_embedded = VLC_FALSE;
 
-    p_vout->p_sys->b_altivec = p_vout->p_libvlc->i_cpu & CPU_CAPABILITY_ALTIVEC;
-    msg_Dbg( p_vout, "we do%s have Altivec", p_vout->p_sys->b_altivec ? "" : "n't" );
-    
+    p_vout->p_sys->b_cpu_has_simd =
+        vlc_CPU() & (CPU_CAPABILITY_ALTIVEC|CPU_CAPABILITY_MMXEXT);
+    msg_Dbg( p_vout, "we do%s have SIMD enabled CPU", p_vout->p_sys->b_cpu_has_simd ? "" : "n't" );
     /* Initialize QuickTime */
-    p_vout->p_sys->h_img_descr = 
+    p_vout->p_sys->h_img_descr =
         (ImageDescriptionHandle)NewHandleClear( sizeof(ImageDescription) );
     p_vout->p_sys->p_matrix =
         (MatrixRecordPtr)malloc( sizeof(MatrixRecord) );
@@ -159,11 +165,11 @@ int E_(OpenVideoQT) ( vlc_object_t *p_this )
         return VLC_EGENERIC;
     }
 
-    /* Damn QT isn't thread safe. so keep a lock in the p_vlc object */
-    vlc_mutex_lock( &p_vout->p_vlc->quicktime_lock );
+    /* Damn QT isn't thread safe. so keep a lock in the p_libvlc object */
+    vlc_mutex_lock( &p_vout->p_libvlc->quicktime_lock );
 
     /* Can we find the right chroma ? */
-    if( p_vout->p_sys->b_altivec )
+    if( p_vout->p_sys->b_cpu_has_simd )
     {
         err = FindCodec( kYUVSPixelFormat, bestSpeedCodec,
                         nil, &p_vout->p_sys->img_dc );
@@ -173,11 +179,11 @@ int E_(OpenVideoQT) ( vlc_object_t *p_this )
         err = FindCodec( kYUV420CodecType, bestSpeedCodec,
                         nil, &p_vout->p_sys->img_dc );
     }
-    vlc_mutex_unlock( &p_vout->p_vlc->quicktime_lock );
-    
+    vlc_mutex_unlock( &p_vout->p_libvlc->quicktime_lock );
     if( err == noErr && p_vout->p_sys->img_dc != 0 )
     {
-        if( p_vout->p_sys->b_altivec )
+        if( p_vout->p_sys->b_cpu_has_simd )
         {
             p_vout->output.i_chroma = VLC_FOURCC('Y','U','Y','2');
             p_vout->p_sys->i_codec = kYUVSPixelFormat;
@@ -198,42 +204,22 @@ int E_(OpenVideoQT) ( vlc_object_t *p_this )
         free( p_vout->p_sys->p_matrix );
         DisposeHandle( (Handle)p_vout->p_sys->h_img_descr );
         free( p_vout->p_sys );
-        return VLC_EGENERIC;        
+        return VLC_EGENERIC;
     }
 
-#define o_qtview p_vout->p_sys->o_qtview
-    o_qtview = [[VLCQTView alloc] initWithVout: p_vout];
-    [o_qtview autorelease];
-
-    if( p_vout->p_sys->b_embedded )
-    {
-        /* Zero the clipping rectangle */
-        p_vout->p_sys->clipping_rect.left = 0;
-        p_vout->p_sys->clipping_rect.right = 0;
-        p_vout->p_sys->clipping_rect.top = 0;
-        p_vout->p_sys->clipping_rect.bottom = 0;
-    }
-    else
+    if( p_vout->b_fullscreen || !p_vout->p_sys->b_embedded )
     {
         /* Spawn window */
+#define o_qtview p_vout->p_sys->o_qtview
+        o_qtview = [[VLCQTView alloc] initWithVout: p_vout];
+        [o_qtview autorelease];
+
         p_vout->p_sys->o_vout_view = [VLCVoutView getVoutView: p_vout
                     subView: o_qtview frame: nil];
         if( !p_vout->p_sys->o_vout_view )
         {
             return VLC_EGENERIC;
         }
-    }
-
-    /* Retrieve the QuickDraw port */
-    if( p_vout->p_sys->b_embedded )
-    {
-        /* Don't need (nor want) to lock the focus, since otherwise we crash
-         * (presumably because we don't own the window, but I'm not sure
-         * if this is the exact reason)  -andrep */
-        p_vout->p_sys->p_qdport = [o_qtview qdPort];
-    }
-    else
-    {
         [o_qtview lockFocus];
         p_vout->p_sys->p_qdport = [o_qtview qdPort];
         [o_qtview unlockFocus];
@@ -251,7 +237,7 @@ void E_(CloseVideoQT) ( vlc_object_t *p_this )
     NSAutoreleasePool *o_pool = [[NSAutoreleasePool alloc] init];
     vout_thread_t * p_vout = (vout_thread_t *)p_this;
 
-    if( !p_vout->p_sys->b_embedded )
+    if( p_vout->b_fullscreen || !p_vout->p_sys->b_embedded )
         [p_vout->p_sys->o_vout_view closeVout];
 
     /* Clean Up Quicktime environment */
@@ -280,17 +266,27 @@ static int InitVideo    ( vout_thread_t *p_vout )
     p_vout->output.i_height = p_vout->render.i_height;
     p_vout->output.i_aspect = p_vout->render.i_aspect;
 
-    /* If we are embedded (e.g. running as a Mozilla plugin), use the pointer
+    if( p_vout->b_fullscreen || !p_vout->p_sys->b_embedded )
+    {
+    Rect s_rect;
+        p_vout->p_sys->clip_mask = NULL;
+    GetPortBounds( p_vout->p_sys->p_qdport, &s_rect );
+    p_vout->p_sys->i_origx = s_rect.left;
+    p_vout->p_sys->i_origy = s_rect.top;
+    p_vout->p_sys->i_width = s_rect.right - s_rect.left;
+    p_vout->p_sys->i_height = s_rect.bottom - s_rect.top;
+    }
+    else
+    {
+    /* As we are embedded (e.g. running as a Mozilla plugin), use the pointer
      * stored in the "drawable" value as the CGrafPtr for the QuickDraw
      * graphics port */
-    if( p_vout->p_sys->b_embedded )
-    {
-        vlc_value_t val;
-        var_Get( p_vout->p_vlc, "drawable", &val );
-        p_vout->p_sys->p_qdport = (CGrafPtr) val.i_int;
+        /* Create the clipping mask */
+        p_vout->p_sys->clip_mask = NewRgn();
+    UpdateEmbeddedGeometry(p_vout);
+    var_AddCallback(p_vout->p_libvlc, "drawableredraw", DrawableRedraw, p_vout);
     }
 
-    SetPort( p_vout->p_sys->p_qdport );
     QTScaleMatrix( p_vout );
 
     if( QTCreateSequence( p_vout ) )
@@ -338,6 +334,12 @@ static void EndVideo( vout_thread_t *p_vout )
 
     QTDestroySequence( p_vout );
 
+    if( !p_vout->b_fullscreen && p_vout->p_sys->b_embedded )
+    {
+    var_DelCallback(p_vout->p_libvlc, "drawableredraw", DrawableRedraw, p_vout);
+    DisposeRgn(p_vout->p_sys->clip_mask);
+    }
+
     /* Free the direct buffers we allocated */
     for( i_index = I_OUTPUTPICTURES; i_index; )
     {
@@ -354,12 +356,9 @@ static void EndVideo( vout_thread_t *p_vout )
  *****************************************************************************/
 static int ManageVideo( vout_thread_t *p_vout )
 {
-    vlc_value_t val;
-    var_Get( p_vout->p_vlc, "drawableredraw", &val );
-
     if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE )
     {
-        if( CoToggleFullscreen( p_vout ) )  
+        if( CoToggleFullscreen( p_vout ) )
         {
             return( 1 );
         }
@@ -367,16 +366,25 @@ static int ManageVideo( vout_thread_t *p_vout )
         p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
     }
 
-    if( p_vout->p_sys->b_embedded && val.i_int == 1 )
+    if( p_vout->i_changes & VOUT_SIZE_CHANGE )
     {
-        /* If we're embedded, the application is expected to indicate a
-         * window change (move/resize/etc) via the "drawableredraw" value.
-         * If that's the case, set the VOUT_SIZE_CHANGE flag so we do
-         * actually handle the window change. */
-        val.i_int = 0;
-        var_Set( p_vout->p_vlc, "drawableredraw", val );
-
-        p_vout->i_changes |= VOUT_SIZE_CHANGE;
+    if( p_vout->b_fullscreen || !p_vout->p_sys->b_embedded )
+    {
+        /* get the geometry from NSQuickDrawView */
+        Rect s_rect;
+        GetPortBounds( p_vout->p_sys->p_qdport, &s_rect );
+        p_vout->p_sys->i_origx = s_rect.left;
+        p_vout->p_sys->i_origy = s_rect.top;
+        p_vout->p_sys->i_width = s_rect.right - s_rect.left;
+        p_vout->p_sys->i_height = s_rect.bottom - s_rect.top;
+    }
+    else
+    {
+        /* As we're embedded, get the geometry from Mozilla/Safari NPWindow object */
+        UpdateEmbeddedGeometry( p_vout );
+        SetDSequenceMask(p_vout->p_sys->i_seq,
+        p_vout->p_sys->clip_mask);
+    }
     }
 
     if( p_vout->i_changes & VOUT_SIZE_CHANGE ||
@@ -394,6 +402,8 @@ static int ManageVideo( vout_thread_t *p_vout )
     {
         p_vout->i_changes &= ~VOUT_ASPECT_CHANGE;
     }
+
+    // can be nil
     [p_vout->p_sys->o_vout_view manage];
 
     return( 0 );
@@ -408,55 +418,34 @@ static void DisplayVideo( vout_thread_t *p_vout, picture_t *p_pic )
 {
     OSErr err;
     CodecFlags flags;
-
-    Rect saved_rect;
-    RgnHandle saved_clip;
-
-    saved_clip = NewRgn();
-
-    if( p_vout->p_sys->b_embedded )
-    {
-        /* In the Mozilla plugin, the browser also draws things in the windows.
-         * So, we have to update the origin and clipping rectangle for each
-         * picture.  FIXME: The vout should probably lock something ... */
-
-        /* Save the origin and clipping rectangle used by the host application
-         * (e.g. Mozilla), so we can restore it later */
-        GetPortBounds( p_vout->p_sys->p_qdport, &saved_rect );
-        GetClip( saved_clip );
-
-        /* The port gets unlocked at the end of this function */
-        LockPortBits( p_vout->p_sys->p_qdport );
-
-        /* Change the origin and clipping to the coordinates that the embedded
-         * window wants to draw at */
-        SetPort( p_vout->p_sys->p_qdport );
-        SetOrigin( p_vout->p_sys->portx , p_vout->p_sys->porty );
-        ClipRect( &p_vout->p_sys->clipping_rect );
-    }
-
+    if( (NULL == p_vout->p_sys->clip_mask) || !EmptyRgn(p_vout->p_sys->clip_mask) )
+    {
+    //CGrafPtr oldPort;
+    //Rect oldBounds;
+
+    /* since there is not way to lock a QuickDraw port for exclusive use
+       there is a potential problem that the frame will be displayed
+       in the wrong place if other embedded plugins redraws as the port
+       origin may be changed */
+    //GetPort(&oldPort);
+    //GetPortBounds(p_vout->p_sys->p_qdport, &oldBounds);
+    SetPort(p_vout->p_sys->p_qdport);
+    SetOrigin(p_vout->p_sys->i_origx, p_vout->p_sys->i_origy);
     if( ( err = DecompressSequenceFrameWhen(
-                    p_vout->p_sys->i_seq,
-                    p_pic->p_sys->p_data,
-                    p_pic->p_sys->i_size,
-                    codecFlagUseImageBuffer, &flags, NULL, NULL ) != noErr ) )
+            p_vout->p_sys->i_seq,
+            p_pic->p_sys->p_data,
+            p_pic->p_sys->i_size,
+            codecFlagUseImageBuffer, &flags, NULL, NULL ) == noErr ) )
     {
-        msg_Warn( p_vout, "QT failed to display the frame sequence: %d", err );
+        QDFlushPortBuffer( p_vout->p_sys->p_qdport, p_vout->p_sys->clip_mask );
+        //QDFlushPortBuffer( p_vout->p_sys->p_qdport, NULL );
     }
     else
     {
-        if( !p_vout->p_sys->b_embedded )
-            QDFlushPortBuffer( p_vout->p_sys->p_qdport, nil );
+        msg_Warn( p_vout, "QT failed to display the frame sequence: %d", err );
     }
-
-    if( p_vout->p_sys->b_embedded )
-    {
-        /* Restore the origin and clipping rectangle to the settings used
-         * by the host application */
-        SetOrigin( saved_rect.left, saved_rect.top );
-        SetClip( saved_clip );
-
-        UnlockPortBits( p_vout->p_sys->p_qdport );
+    //SetPortBounds(p_vout->p_sys->p_qdport, &oldBounds);
+    //SetPort(oldPort);
     }
 }
 
@@ -482,7 +471,7 @@ static int ControlVideo( vout_thread_t *p_vout, int i_query, va_list args )
 }
 
 /*****************************************************************************
- * CoToggleFullscreen: toggle fullscreen 
+ * CoToggleFullscreen: toggle fullscreen
  *****************************************************************************
  * Returns 0 on success, 1 otherwise
  *****************************************************************************/
@@ -490,105 +479,95 @@ static int CoToggleFullscreen( vout_thread_t *p_vout )
 {
     NSAutoreleasePool *o_pool = [[NSAutoreleasePool alloc] init];
 
-    QTDestroySequence( p_vout );
-
-    if( !p_vout->b_fullscreen )
-    {
-        /* Save window size and position */
-        p_vout->p_sys->s_frame.size =
-            [p_vout->p_sys->o_vout_view frame].size;
-        p_vout->p_sys->s_frame.origin =
-            [[p_vout->p_sys->o_vout_view getWindow] frame].origin;
-        p_vout->p_sys->b_saved_frame = VLC_TRUE;
-    }
-    [p_vout->p_sys->o_vout_view closeVout];
-
     p_vout->b_fullscreen = !p_vout->b_fullscreen;
 
-#define o_qtview p_vout->p_sys->o_qtview
-    o_qtview = [[VLCQTView alloc] initWithVout: p_vout];
-    [o_qtview autorelease];
-    
-    if( p_vout->p_sys->b_saved_frame )
-    {
-        p_vout->p_sys->o_vout_view = [VLCVoutView getVoutView: p_vout
-            subView: o_qtview
-            frame: &p_vout->p_sys->s_frame];
-    }
+    if( p_vout->b_fullscreen )
+        [p_vout->p_sys->o_vout_view enterFullscreen];
     else
-    {
-        p_vout->p_sys->o_vout_view = [VLCVoutView getVoutView: p_vout
-            subView: o_qtview frame: nil];
-    }
+        [p_vout->p_sys->o_vout_view leaveFullscreen];
 
-    /* Retrieve the QuickDraw port */
-    [o_qtview lockFocus];
-    p_vout->p_sys->p_qdport = [o_qtview qdPort];
-    [o_qtview unlockFocus];
-#undef o_qtview
+    [o_pool release];
+    return 0;
+}
 
-    SetPort( p_vout->p_sys->p_qdport );
-    QTScaleMatrix( p_vout );
+/* If we're embedded, the application is expected to indicate a
+ * window change (move/resize/etc) via the "drawableredraw" value.
+ * If that's the case, set the VOUT_SIZE_CHANGE flag so we do
+ * actually handle the window change. */
 
-    if( QTCreateSequence( p_vout ) )
+static int DrawableRedraw( vlc_object_t *p_this, const char *psz_name,
+    vlc_value_t oval, vlc_value_t nval, void *param)
+{
+    /* ignore changes until we are ready for them */
+    if( (oval.i_int != nval.i_int) && (nval.i_int == 1) )
     {
-        msg_Err( p_vout, "unable to initialize QT: QTCreateSequence failed" );
-        return( 1 );
+    vout_thread_t *p_vout = (vout_thread_t *)param;
+    /* prevent QT from rendering any more video until we have updated
+       the geometry */
+    SetEmptyRgn(p_vout->p_sys->clip_mask);
+    SetDSequenceMask(p_vout->p_sys->i_seq,
+        p_vout->p_sys->clip_mask);
+
+    p_vout->i_changes |= VOUT_SIZE_CHANGE;
     }
+    return VLC_SUCCESS;
+}
 
-    [o_pool release];
-    return 0;
+/* Embedded video get their drawing region from the host application
+ * by the drawable values here.  Read those variables, and store them
+ * in the p_vout->p_sys structure so that other functions (such as
+ * DisplayVideo and ManageVideo) can use them later. */
+
+static void UpdateEmbeddedGeometry( vout_thread_t *p_vout )
+{
+    vlc_value_t val;
+    vlc_value_t valt, vall, valb, valr, valx, valy, valw, valh,
+        valportx, valporty;
+
+    var_Get( p_vout->p_libvlc, "drawable", &val );
+    var_Get( p_vout->p_libvlc, "drawablet", &valt );
+    var_Get( p_vout->p_libvlc, "drawablel", &vall );
+    var_Get( p_vout->p_libvlc, "drawableb", &valb );
+    var_Get( p_vout->p_libvlc, "drawabler", &valr );
+    var_Get( p_vout->p_libvlc, "drawablex", &valx );
+    var_Get( p_vout->p_libvlc, "drawabley", &valy );
+    var_Get( p_vout->p_libvlc, "drawablew", &valw );
+    var_Get( p_vout->p_libvlc, "drawableh", &valh );
+    var_Get( p_vout->p_libvlc, "drawableportx", &valportx );
+    var_Get( p_vout->p_libvlc, "drawableporty", &valporty );
+
+    /* portx, porty contains values for SetOrigin() function
+       which isn't used, instead use QT Translate matrix */
+    p_vout->p_sys->i_origx = valportx.i_int;
+    p_vout->p_sys->i_origy = valporty.i_int;
+    p_vout->p_sys->p_qdport = (CGrafPtr) val.i_int;
+    p_vout->p_sys->i_width = valw.i_int;
+    p_vout->p_sys->i_height = valh.i_int;
+
+    /* update video clipping mask */
+    /*SetRectRgn( p_vout->p_sys->clip_mask , vall.i_int ,
+        valt.i_int, valr.i_int, valb.i_int );*/
+    SetRectRgn( p_vout->p_sys->clip_mask , vall.i_int + valportx.i_int ,
+        valt.i_int + valporty.i_int , valr.i_int + valportx.i_int ,
+        valb.i_int + valporty.i_int );
+
+    /* reset drawableredraw variable indicating we are ready
+       to take changes in video geometry */
+    val.i_int=0;
+    var_Set( p_vout->p_libvlc, "drawableredraw", val );
 }
 
 /*****************************************************************************
- * QTScaleMatrix: scale matrix 
+ * QTScaleMatrix: scale matrix
  *****************************************************************************/
 static void QTScaleMatrix( vout_thread_t *p_vout )
 {
-    Rect s_rect;
     vlc_value_t val;
-    unsigned int i_width, i_height;
     Fixed factor_x, factor_y;
     unsigned int i_offset_x = 0;
     unsigned int i_offset_y = 0;
-
-    GetPortBounds( p_vout->p_sys->p_qdport, &s_rect );
-
-    i_width = s_rect.right - s_rect.left;
-    i_height = s_rect.bottom - s_rect.top;
-
-    if( p_vout->p_sys->b_embedded )
-    {
-        /* Embedded video get their drawing region from the host application
-         * by the drawable values here.  Read those variables, and store them
-         * in the p_vout->p_sys structure so that other functions (such as
-         * DisplayVideo and ManageVideo) can use them later. */
-        vlc_value_t valt, vall, valb, valr, valx, valy, valw, valh,
-                    valportx, valporty;
-
-        var_Get( p_vout->p_vlc, "drawable", &val );
-        var_Get( p_vout->p_vlc, "drawablet", &valt );
-        var_Get( p_vout->p_vlc, "drawablel", &vall );
-        var_Get( p_vout->p_vlc, "drawableb", &valb );
-        var_Get( p_vout->p_vlc, "drawabler", &valr );
-        var_Get( p_vout->p_vlc, "drawablex", &valx );
-        var_Get( p_vout->p_vlc, "drawabley", &valy );
-        var_Get( p_vout->p_vlc, "drawablew", &valw );
-        var_Get( p_vout->p_vlc, "drawableh", &valh );
-        var_Get( p_vout->p_vlc, "drawableportx", &valportx );
-        var_Get( p_vout->p_vlc, "drawableporty", &valporty );
-
-        p_vout->p_sys->portx = valportx.i_int;
-        p_vout->p_sys->porty = valporty.i_int;
-        p_vout->p_sys->p_qdport = (CGrafPtr) val.i_int;
-        i_width = valw.i_int;
-        i_height = valh.i_int;
-
-        p_vout->p_sys->clipping_rect.top = 0;
-        p_vout->p_sys->clipping_rect.left = 0;
-        p_vout->p_sys->clipping_rect.bottom = valb.i_int - valt.i_int;
-        p_vout->p_sys->clipping_rect.right = valr.i_int - vall.i_int;
-    }
+    int i_width = p_vout->p_sys->i_width;
+    int i_height = p_vout->p_sys->i_height;
 
     var_Get( p_vout, "macosx-stretch", &val );
     if( val.b_bool )
@@ -642,7 +621,7 @@ static void QTScaleMatrix( vout_thread_t *p_vout )
 }
 
 /*****************************************************************************
- * QTCreateSequence: create a new sequence 
+ * QTCreateSequence: create a new sequence
  *****************************************************************************
  * Returns 0 on success, 1 otherwise
  *****************************************************************************/
@@ -671,7 +650,7 @@ static int QTCreateSequence( vout_thread_t *p_vout )
 
     HUnlock( (Handle)p_vout->p_sys->h_img_descr );
 
-    if( ( err = DecompressSequenceBeginS( 
+    if( ( err = DecompressSequenceBeginS(
                               &p_vout->p_sys->i_seq,
                               p_vout->p_sys->h_img_descr,
                               NULL,
@@ -679,7 +658,7 @@ static int QTCreateSequence( vout_thread_t *p_vout )
                               p_vout->p_sys->p_qdport,
                               NULL, NULL,
                               p_vout->p_sys->p_matrix,
-                              srcCopy, NULL,
+                              srcCopy, p_vout->p_sys->clip_mask,
                               codecFlagUseImageBuffer,
                               codecLosslessQuality,
                               bestSpeedCodec ) ) )
@@ -692,7 +671,7 @@ static int QTCreateSequence( vout_thread_t *p_vout )
 }
 
 /*****************************************************************************
- * QTDestroySequence: destroy sequence 
+ * QTDestroySequence: destroy sequence
  *****************************************************************************/
 static void QTDestroySequence( vout_thread_t *p_vout )
 {
@@ -739,17 +718,17 @@ static int QTNewPicture( vout_thread_t *p_vout, picture_t *p_pic )
             p_pic->p_sys->p_data = (void *)p_pic->p[0].p_pixels;
 
             break;
-            
         case VLC_FOURCC('I','4','2','0'):
             p_pic->p_sys->p_data = (void *)&p_pic->p_sys->pixmap_i420;
             p_pic->p_sys->i_size = sizeof(PlanarPixmapInfoYUV420);
-            
             /* Allocate the memory buffer */
             p_pic->p_data = vlc_memalign( &p_pic->p_data_orig,
                                           16, p_vout->output.i_width * p_vout->output.i_height * 3 / 2 );
 
             /* Y buffer */
-            p_pic->Y_PIXELS = p_pic->p_data; 
+            p_pic->Y_PIXELS = p_pic->p_data;
             p_pic->p[Y_PLANE].i_lines = p_vout->output.i_height;
             p_pic->p[Y_PLANE].i_visible_lines = p_vout->output.i_height;
             p_pic->p[Y_PLANE].i_pitch = p_vout->output.i_width;
@@ -788,7 +767,7 @@ static int QTNewPicture( vout_thread_t *p_vout, picture_t *p_pic )
             P.componentInfoCr.rowBytes = p_vout->output.i_width / 2;
 #undef P
             break;
-        
         default:
             /* Unknown chroma, tell the guy to get lost */
             free( p_pic->p_sys );
@@ -821,6 +800,76 @@ static void QTFreePicture( vout_thread_t *p_vout, picture_t *p_pic )
  *****************************************************************************/
 @implementation VLCQTView
 
+/* This function will reset the o_vout_view. It's useful to go fullscreen. */
++ (void)resetVout: (vout_thread_t *)p_vout
+{
+    QTDestroySequence( p_vout );
+
+    if( p_vout->b_fullscreen )
+    {
+    if( !p_vout->p_sys->b_embedded )
+    {
+        /* Save window size and position */
+        p_vout->p_sys->s_frame.size =
+        [p_vout->p_sys->o_vout_view frame].size;
+        p_vout->p_sys->s_frame.origin =
+        [[p_vout->p_sys->o_vout_view getWindow] frame].origin;
+        p_vout->p_sys->b_saved_frame = VLC_TRUE;
+    }
+        else
+        {
+            var_DelCallback(p_vout->p_libvlc, "drawableredraw", DrawableRedraw, p_vout);
+            DisposeRgn(p_vout->p_sys->clip_mask);
+        }
+    }
+
+    if( p_vout->b_fullscreen || !p_vout->p_sys->b_embedded )
+    {
+    Rect s_rect;
+        p_vout->p_sys->clip_mask = NULL;
+#define o_qtview p_vout->p_sys->o_qtview
+    o_qtview = [[VLCQTView alloc] initWithVout: p_vout];
+    [o_qtview autorelease];
+    
+    if( p_vout->p_sys->b_saved_frame )
+    {
+        p_vout->p_sys->o_vout_view = [VLCVoutView getVoutView: p_vout
+        subView: o_qtview
+        frame: &p_vout->p_sys->s_frame];
+    }
+    else
+    {
+        p_vout->p_sys->o_vout_view = [VLCVoutView getVoutView: p_vout
+        subView: o_qtview frame: nil];
+    }
+
+    /* Retrieve the QuickDraw port */
+    [o_qtview lockFocus];
+    p_vout->p_sys->p_qdport = [o_qtview qdPort];
+    [o_qtview unlockFocus];
+#undef o_qtview
+    GetPortBounds( p_vout->p_sys->p_qdport, &s_rect );
+    p_vout->p_sys->i_origx = s_rect.left;
+    p_vout->p_sys->i_origy = s_rect.top;
+    p_vout->p_sys->i_width = s_rect.right - s_rect.left;
+    p_vout->p_sys->i_height = s_rect.bottom - s_rect.top;
+    }
+    else
+    {
+        /* Create the clipping mask */
+        p_vout->p_sys->clip_mask = NewRgn();
+    UpdateEmbeddedGeometry(p_vout);
+    var_AddCallback(p_vout->p_libvlc, "drawableredraw", DrawableRedraw, p_vout);
+    }
+    QTScaleMatrix( p_vout );
+
+    if( QTCreateSequence( p_vout ) )
+    {
+        msg_Err( p_vout, "unable to initialize QT: QTCreateSequence failed" );
+        return;
+    }
+}
+
 - (id) initWithVout:(vout_thread_t *)_p_vout
 {
     p_vout = _p_vout;