Commit ff146815 authored by Andre Pang's avatar Andre Pang

* modules/macosx/{vout,voutqt}.m: The Mac OS X Mozilla plugin lives again!


Some details:

* This was mostly taken verbatim from revision:5717 (before the vout
  Mozilla support was removed), though it's been edited pretty thoroughly,
  and is now much more commented.

* The "normal" vout display should be completely unaffected, since the
  plugin-relevant code paths are only taken when p_vout->p_sys->b_embedded is
  set to VLC_TRUE.  (I've tested the normal VLC.app, and it seems fine.)

* There are still some problems with the plugin when the Mozilla window is
  resized a lot.  I suspect this is due to threading issues with
  QuickDraw, but I don't know enough about QuickDraw to be sure.  Help
  with this would be very welcome.

* The original patch in revision:5717 optimised the plugin display
  slightly, by using a mask (clipping region) so that QuickDraw only
  updated the plugin's area of the dirty region.  I elected not to use
  a mask, since I thought the extra code complexity (i.e. lots more if()
  branches) isn't worth the incremental speedup.  (If, in fact, there was
  a speedup at all -- the extra overhead induced by calculating the
  intersection of the dirty region with the mask may have offset any
  benefits: only benchmarks will tell ...)
parent 909088e8
......@@ -48,25 +48,35 @@
- (id)initWithVout:(vout_thread_t *)_p_vout frame:(NSRect *)s_frame
{
int i_timeout;
vlc_value_t value_drawable;
p_vout = _p_vout;
/* Wait for a MacOS X interface to appear. Timeout is 2 seconds. */
for( i_timeout = 20 ; i_timeout-- ; )
var_Get( p_vout->p_vlc, "drawable", &value_drawable );
/* We only wait for NSApp to initialise if we're not embedded (as in the
* case of the Mozilla plugin). We can tell whether we're embedded or not
* by examining the "drawable" value: if it's zero, we're running in the
* main Mac intf; if it's non-zero, we're embedded. */
if( value_drawable.i_int == 0 )
{
/* 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 )
{
msleep( INTF_IDLE_SLEEP );
/* No MacOS X intf, unable to communicate with MT */
msg_Err( p_vout, "no MacOS X interface present" );
return NULL;
}
}
if( NSApp == NULL )
{
/* No MacOS X intf, unable to communicate with MT */
msg_Err( p_vout, "no MacOS X interface present" );
return NULL;
}
/* p_real_vout: the vout we have to use to check for video-on-top
and a few other things. If we are the QuickTime output, it's us.
It we are the OpenGL provider, it is our parent. */
......
......@@ -70,6 +70,11 @@ struct vout_sys_t
MatrixRecordPtr p_matrix;
DecompressorComponent img_dc;
ImageDescriptionHandle h_img_descr;
/* Mozilla plugin-related variables */
vlc_bool_t b_embedded;
Rect clipping_rect;
int portx, porty;
};
struct picture_sys_t
......@@ -104,9 +109,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;
OSErr err;
vlc_value_t value_drawable;
p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
if( p_vout->p_sys == NULL )
......@@ -126,12 +132,31 @@ int E_(OpenVideoQT) ( vlc_object_t *p_this )
p_vout->pf_display = DisplayVideo;
p_vout->pf_control = ControlVideo;
/* Spawn window */
p_vout->p_sys->o_window =
[[VLCWindow alloc] initWithVout: p_vout frame: nil];
if( !p_vout->p_sys->o_window )
/* 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 );
if( value_drawable.i_int != 0 )
p_vout->p_sys->b_embedded = VLC_TRUE;
else
p_vout->p_sys->b_embedded = VLC_FALSE;
if( p_vout->p_sys->b_embedded )
{
return VLC_EGENERIC;
/* 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
{
/* Spawn window */
p_vout->p_sys->o_window =
[[VLCWindow alloc] initWithVout: p_vout frame: nil];
if( !p_vout->p_sys->o_window )
{
return VLC_EGENERIC;
}
}
p_vout->p_sys->b_altivec = p_vout->p_libvlc->i_cpu & CPU_CAPABILITY_ALTIVEC;
......@@ -200,9 +225,19 @@ int E_(OpenVideoQT) ( vlc_object_t *p_this )
[o_qtview autorelease];
/* Retrieve the QuickDraw port */
[o_qtview lockFocus];
p_vout->p_sys->p_qdport = [o_qtview qdPort];
[o_qtview unlockFocus];
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];
}
#undef o_qtview
return VLC_SUCCESS;
......@@ -216,7 +251,8 @@ void E_(CloseVideoQT) ( vlc_object_t *p_this )
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->p_sys->b_embedded )
[p_vout->p_sys->o_window close];
/* Clean Up Quicktime environment */
ExitMovies();
......@@ -244,6 +280,16 @@ 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
* 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;
}
SetPort( p_vout->p_sys->p_qdport );
QTScaleMatrix( p_vout );
......@@ -308,6 +354,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 ) )
......@@ -318,17 +367,28 @@ 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->p_sys->b_embedded && val.i_int == 1 )
{
/* 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->i_changes & VOUT_SIZE_CHANGE )
{
QTScaleMatrix( p_vout );
SetDSequenceMatrix( p_vout->p_sys->i_seq,
SetDSequenceMatrix( p_vout->p_sys->i_seq,
p_vout->p_sys->p_matrix );
p_vout->i_changes &= ~VOUT_SIZE_CHANGE;
}
[p_vout->p_sys->o_window manage];
return( 0 );
}
......@@ -342,17 +402,54 @@ static void DisplayVideo( vout_thread_t *p_vout, picture_t *p_pic )
OSErr err;
CodecFlags flags;
if( ( err = DecompressSequenceFrameWhen(
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( ( err = DecompressSequenceFrameWhen(
p_vout->p_sys->i_seq,
p_pic->p_sys->p_data,
p_pic->p_sys->i_size,
p_pic->p_sys->i_size,
codecFlagUseImageBuffer, &flags, NULL, NULL ) != noErr ) )
{
msg_Warn( p_vout, "DecompressSequenceFrameWhen failed: %d", err );
}
else
{
QDFlushPortBuffer( p_vout->p_sys->p_qdport, nil );
if( !p_vout->p_sys->b_embedded )
QDFlushPortBuffer( p_vout->p_sys->p_qdport, nil );
}
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 );
}
}
......@@ -453,6 +550,39 @@ static void QTScaleMatrix( vout_thread_t *p_vout )
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;
}
var_Get( p_vout, "macosx-stretch", &val );
if( val.b_bool )
{
......@@ -460,7 +590,7 @@ 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 )
{
......@@ -486,13 +616,13 @@ static void QTScaleMatrix( vout_thread_t *p_vout )
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) );
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment