]> git.sesse.net Git - vlc/blobdiff - modules/gui/macosx/voutqt.m
Removes trailing spaces. Removes tabs.
[vlc] / modules / gui / macosx / voutqt.m
index 95e777b65782d8168fd57a57f43645d5746c70e5..fcbd6785300d5427a486878d095c4070585c1f43 100644 (file)
@@ -1,20 +1,21 @@
 /*****************************************************************************
  * vout.m: MacOS X video output module
  *****************************************************************************
- * Copyright (C) 2001-2003 VideoLAN
- * $Id: vout.m 8351 2004-08-02 13:06:38Z hartman $
+ * Copyright (C) 2001-2004 the VideoLAN team
+ * $Id$
  *
  * Authors: Colin Delacroix <colin@zoy.org>
  *          Florian G. Pflug <fgp@phlo.org>
  *          Jon Lech Johansen <jon-vl@nanocrew.net>
  *          Derk-Jan Hartman <hartman at videolan dot org>
  *          Eric Petit <titer@m0k.org>
+ *          Benjamin Pracht <bigben AT videolan DOT org>
  *
  * This program is free software; you can redistribute it and/or modify
  * 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
@@ -22,7 +23,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  *****************************************************************************/
 
 /*****************************************************************************
 /*****************************************************************************
  * 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
 {
     NSAutoreleasePool *o_pool;
-    VLCWindow * o_window;
     VLCQTView * o_qtview;
+    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;
@@ -70,13 +71,20 @@ struct vout_sys_t
     MatrixRecordPtr p_matrix;
     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;
+    RgnHandle clip_mask;
 };
 
 struct picture_sys_t
 {
     void *p_data;
     unsigned int i_size;
-    
+
     /* When using I420 output */
     PlanarPixmapInfoYUV420 pixmap_i420;
 };
@@ -92,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 * );
@@ -104,11 +115,10 @@ static void QTFreePicture       ( vout_thread_t *, picture_t * );
  * This function allocates and initializes a MacOS X vout method.
  *****************************************************************************/
 int E_(OpenVideoQT) ( vlc_object_t *p_this )
-{   
+{
     vout_thread_t * p_vout = (vout_thread_t *)p_this;
-    vlc_value_t val;
     OSErr err;
-    int i_timeout;
+    vlc_value_t value_drawable;
 
     p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
     if( p_vout->p_sys == NULL )
@@ -119,22 +129,7 @@ int E_(OpenVideoQT) ( vlc_object_t *p_this )
 
     memset( p_vout->p_sys, 0, sizeof( vout_sys_t ) );
 
-    /* Wait for a MacOS X interface to appear. Timeout is 2 seconds. */
-    for( i_timeout = 20 ; i_timeout-- ; )
-    {
-        if( NSApp == NULL )
-        {
-            msleep( INTF_IDLE_SLEEP );
-        }
-    }
-
-    if( NSApp == NULL )
-    {
-        /* no MacOS X intf, unable to communicate with MT */
-        msg_Err( p_vout, "no MacOS X interface present" );
-        free( p_vout->p_sys );
-        return( 1 );
-    }
+    p_vout->p_sys->o_pool = [[NSAutoreleasePool alloc] init];
 
     p_vout->pf_init = InitVideo;
     p_vout->pf_end = EndVideo;
@@ -143,38 +138,40 @@ int E_(OpenVideoQT) ( vlc_object_t *p_this )
     p_vout->pf_display = DisplayVideo;
     p_vout->pf_control = ControlVideo;
 
-    p_vout->p_sys->o_pool = [[NSAutoreleasePool alloc] init];
+    /* 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_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;
 
-    var_Create( p_vout, "macosx-vdev", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
-    var_Create( p_vout, "macosx-fill", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
-    var_Create( p_vout, "macosx-stretch", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
-    var_Create( p_vout, "macosx-opaqueness", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT );
-    
-    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) );
 
     if( ( err = EnterMovies() ) != noErr )
     {
-        msg_Err( p_vout, "EnterMovies failed: %d", err );
+        msg_Err( p_vout, "QT initialization failed: EnterMovies failed: %d", err );
         free( p_vout->p_sys->p_matrix );
         DisposeHandle( (Handle)p_vout->p_sys->h_img_descr );
         free( p_vout->p_sys );
         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( kComponentVideoUnsigned, bestSpeedCodec,
+        err = FindCodec( kYUVSPixelFormat, bestSpeedCodec,
                         nil, &p_vout->p_sys->img_dc );
     }
     else
@@ -182,14 +179,14 @@ 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 = kComponentVideoUnsigned;
+            p_vout->p_sys->i_codec = kYUVSPixelFormat;
         }
         else
         {
@@ -199,7 +196,7 @@ int E_(OpenVideoQT) ( vlc_object_t *p_this )
     }
     else
     {
-        msg_Err( p_vout, "failed to find an appropriate codec" );
+        msg_Err( p_vout, "QT doesn't support any appropriate chroma" );
     }
 
     if( p_vout->p_sys->img_dc == 0 )
@@ -207,67 +204,26 @@ 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;
     }
 
-    /* Setup the menuitem for the multiple displays. Read the vlc preference (macosx-vdev) for the primary display */
-    NSArray * o_screens = [NSScreen screens];
-    if( [o_screens count] > 0 && var_Type( p_vout, "video-device" ) == 0 )
+    if( p_vout->b_fullscreen || !p_vout->p_sys->b_embedded )
     {
-        int i = 1;
-        vlc_value_t val2, text;
-        NSScreen * o_screen;
-
-        var_Get( p_vout, "macosx-vdev", &val );
-
-        var_Create( p_vout, "video-device", VLC_VAR_INTEGER |
-                                            VLC_VAR_HASCHOICE ); 
-        text.psz_string = _("Video device");
-        var_Change( p_vout, "video-device", VLC_VAR_SETTEXT, &text, NULL );
-        
-        NSEnumerator * o_enumerator = [o_screens objectEnumerator];
+        /* Spawn window */
+#define o_qtview p_vout->p_sys->o_qtview
+        o_qtview = [[VLCQTView alloc] initWithVout: p_vout];
+        [o_qtview autorelease];
 
-        while( (o_screen = [o_enumerator nextObject]) != NULL )
+        p_vout->p_sys->o_vout_view = [VLCVoutView getVoutView: p_vout
+                    subView: o_qtview frame: nil];
+        if( !p_vout->p_sys->o_vout_view )
         {
-            char psz_temp[255];
-            NSRect s_rect = [o_screen frame];
-
-            snprintf( psz_temp, sizeof(psz_temp)/sizeof(psz_temp[0])-1, 
-                      "%s %d (%dx%d)", _("Screen"), i,
-                      (int)s_rect.size.width, (int)s_rect.size.height ); 
-
-            text.psz_string = psz_temp;
-            val2.i_int = i;
-            var_Change( p_vout, "video-device",
-                        VLC_VAR_ADDCHOICE, &val2, &text );
-
-            if( ( i - 1 ) == val.i_int )
-            {
-                var_Set( p_vout, "video-device", val2 );
-            }
-            i++;
+            return VLC_EGENERIC;
         }
-
-        var_AddCallback( p_vout, "video-device", vout_VarCallback,
-                         NULL );
-
-        val2.b_bool = VLC_TRUE;
-        var_Set( p_vout, "intf-change", val2 );
+        [o_qtview lockFocus];
+        p_vout->p_sys->p_qdport = [o_qtview qdPort];
+        [o_qtview unlockFocus];
     }
-
-    /* Spawn window */
-    p_vout->p_sys->o_window =
-        [[VLCWindow alloc] initWithVout: p_vout frame: nil];
-
-#define o_qtview p_vout->p_sys->o_qtview
-    o_qtview = [[VLCQTView alloc] initWithVout: p_vout];
-    [p_vout->p_sys->o_window setContentView: o_qtview];
-    [o_qtview autorelease];
-
-    /* Retrieve the QuickDraw port */
-    [o_qtview lockFocus];
-    p_vout->p_sys->p_qdport = [o_qtview qdPort];
-    [o_qtview unlockFocus];
 #undef o_qtview
 
     return VLC_SUCCESS;
@@ -278,10 +234,11 @@ int E_(OpenVideoQT) ( vlc_object_t *p_this )
  *****************************************************************************/
 void E_(CloseVideoQT) ( vlc_object_t *p_this )
 {
-    NSAutoreleasePool *o_pool = [[NSAutoreleasePool alloc] init]; 
+    NSAutoreleasePool *o_pool = [[NSAutoreleasePool alloc] init];
     vout_thread_t * p_vout = (vout_thread_t *)p_this;
 
-    [p_vout->p_sys->o_window close];
+    if( p_vout->b_fullscreen || !p_vout->p_sys->b_embedded )
+        [p_vout->p_sys->o_vout_view closeVout];
 
     /* Clean Up Quicktime environment */
     ExitMovies();
@@ -309,12 +266,32 @@ 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;
 
-    SetPort( p_vout->p_sys->p_qdport );
+    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 */
+        /* 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 create sequence" );
+        msg_Err( p_vout, "unable to initialize QT: QTCreateSequence failed" );
         return( 1 );
     }
 
@@ -357,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; )
     {
@@ -375,7 +358,7 @@ static int ManageVideo( vout_thread_t *p_vout )
 {
     if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE )
     {
-        if( CoToggleFullscreen( p_vout ) )  
+        if( CoToggleFullscreen( p_vout ) )
         {
             return( 1 );
         }
@@ -383,17 +366,46 @@ static int ManageVideo( vout_thread_t *p_vout )
         p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
     }
 
-    if( p_vout->i_changes & VOUT_SIZE_CHANGE ) 
+    if( 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 ||
+        p_vout->i_changes & VOUT_ASPECT_CHANGE )
     {
         QTScaleMatrix( p_vout );
-        SetDSequenceMatrix( p_vout->p_sys->i_seq, 
+        SetDSequenceMatrix( p_vout->p_sys->i_seq,
                             p_vout->p_sys->p_matrix );
+    }
+    if( p_vout->i_changes & VOUT_SIZE_CHANGE )
+    {
         p_vout->i_changes &= ~VOUT_SIZE_CHANGE;
     }
+    if( p_vout->i_changes & VOUT_ASPECT_CHANGE )
+    {
+        p_vout->i_changes &= ~VOUT_ASPECT_CHANGE;
+    }
+
+    // can be nil
+    [p_vout->p_sys->o_vout_view manage];
 
-    [p_vout->p_sys->o_window manage];
-    
     return( 0 );
 }
 
@@ -406,18 +418,34 @@ static void DisplayVideo( vout_thread_t *p_vout, picture_t *p_pic )
 {
     OSErr err;
     CodecFlags flags;
-
-    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 ) )
+    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 ) )
     {
-        msg_Warn( p_vout, "DecompressSequenceFrameWhen failed: %d", err );
+        QDFlushPortBuffer( p_vout->p_sys->p_qdport, p_vout->p_sys->clip_mask );
+        //QDFlushPortBuffer( p_vout->p_sys->p_qdport, NULL );
     }
     else
     {
-        QDFlushPortBuffer( p_vout->p_sys->p_qdport, nil );
+        msg_Warn( p_vout, "QT failed to display the frame sequence: %d", err );
+    }
+    //SetPortBounds(p_vout->p_sys->p_qdport, &oldBounds);
+    //SetPort(oldPort);
     }
 }
 
@@ -432,7 +460,7 @@ static int ControlVideo( vout_thread_t *p_vout, int i_query, va_list args )
     {
         case VOUT_SET_STAY_ON_TOP:
             b_arg = va_arg( args, vlc_bool_t );
-            [p_vout->p_sys->o_window setOnTop: b_arg];
+            [p_vout->p_sys->o_vout_view setOnTop: b_arg];
             return VLC_SUCCESS;
 
         case VOUT_CLOSE:
@@ -443,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
  *****************************************************************************/
@@ -451,72 +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_window contentView] frame].size;
-        p_vout->p_sys->s_frame.origin =
-            [p_vout->p_sys->o_window frame].origin;
-        p_vout->p_sys->b_saved_frame = VLC_TRUE;
-    }
-    [p_vout->p_sys->o_window close];
-
     p_vout->b_fullscreen = !p_vout->b_fullscreen;
 
-    if( p_vout->p_sys->b_saved_frame )
-    {
-        p_vout->p_sys->o_window = [[VLCWindow alloc]
-            initWithVout: p_vout 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_window = [[VLCWindow alloc]
-            initWithVout: p_vout frame: nil];
-    }
-
-#define o_qtview p_vout->p_sys->o_qtview
-    o_qtview = [[VLCQTView alloc] initWithVout: p_vout];
-    [p_vout->p_sys->o_window setContentView: o_qtview];
-    [o_qtview autorelease];
+        [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 create sequence" );
-        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);
 
-    [o_pool release];
-    return 0;
+    p_vout->i_changes |= VOUT_SIZE_CHANGE;
+    }
+    return VLC_SUCCESS;
+}
+
+/* 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;
+    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 )
@@ -525,45 +576,52 @@ static void QTScaleMatrix( vout_thread_t *p_vout )
                            Long2Fix( p_vout->output.i_width ) );
         factor_y = FixDiv( Long2Fix( i_height ),
                            Long2Fix( p_vout->output.i_height ) );
-                           
+
     }
-    else if( i_height * p_vout->output.i_aspect < i_width * VOUT_ASPECT_FACTOR )
+    else if( i_height * p_vout->fmt_in.i_visible_width *
+             p_vout->fmt_in.i_sar_num <
+             i_width * p_vout->fmt_in.i_visible_height *
+             p_vout->fmt_in.i_sar_den )
     {
-        int i_adj_width = i_height * p_vout->output.i_aspect /
-                          VOUT_ASPECT_FACTOR;
+        int i_adj_width = i_height * p_vout->fmt_in.i_visible_width *
+                          p_vout->fmt_in.i_sar_num /
+                          ( p_vout->fmt_in.i_sar_den *
+                            p_vout->fmt_in.i_visible_height );
 
         factor_x = FixDiv( Long2Fix( i_adj_width ),
-                           Long2Fix( p_vout->output.i_width ) );
+                           Long2Fix( p_vout->fmt_in.i_visible_width ) );
         factor_y = FixDiv( Long2Fix( i_height ),
-                           Long2Fix( p_vout->output.i_height ) );
+                           Long2Fix( p_vout->fmt_in.i_visible_height ) );
 
         i_offset_x = (i_width - i_adj_width) / 2;
     }
     else
     {
-        int i_adj_height = i_width * VOUT_ASPECT_FACTOR /
-                           p_vout->output.i_aspect;
+        int i_adj_height = i_width * p_vout->fmt_in.i_visible_height *
+                           p_vout->fmt_in.i_sar_den /
+                           ( p_vout->fmt_in.i_sar_num *
+                             p_vout->fmt_in.i_visible_width );
 
         factor_x = FixDiv( Long2Fix( i_width ),
-                           Long2Fix( p_vout->output.i_width ) );
+                           Long2Fix( p_vout->fmt_in.i_visible_width ) );
         factor_y = FixDiv( Long2Fix( i_adj_height ),
-                           Long2Fix( p_vout->output.i_height ) );
+                           Long2Fix( p_vout->fmt_in.i_visible_height ) );
 
         i_offset_y = (i_height - i_adj_height) / 2;
     }
-    
+
     SetIdentityMatrix( p_vout->p_sys->p_matrix );
 
     ScaleMatrix( p_vout->p_sys->p_matrix,
                  factor_x, factor_y,
                  Long2Fix(0), Long2Fix(0) );
-                 
+
     TranslateMatrix( p_vout->p_sys->p_matrix,
                  Long2Fix(i_offset_x), Long2Fix(i_offset_y) );
 }
 
 /*****************************************************************************
- * QTCreateSequence: create a new sequence 
+ * QTCreateSequence: create a new sequence
  *****************************************************************************
  * Returns 0 on success, 1 otherwise
  *****************************************************************************/
@@ -592,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,
@@ -600,12 +658,12 @@ 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 ) ) )
     {
-        msg_Err( p_vout, "DecompressSequenceBeginS failed: %d", err );
+        msg_Err( p_vout, "Failed to initialize QT: DecompressSequenceBeginS failed: %d", err );
         return( 1 );
     }
 
@@ -613,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 )
 {
@@ -660,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;
@@ -709,11 +767,11 @@ 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 );
-            msg_Err( p_vout, "never heard of chroma 0x%.8x (%4.4s)",
+            msg_Err( p_vout, "Unknown chroma format 0x%.8x (%4.4s)",
                      p_vout->output.i_chroma, (char*)&p_vout->output.i_chroma );
             p_pic->i_planes = 0;
             return( -1 );
@@ -742,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;