[vlc-devel] Python+wxPython bindings on Mac (patch)
Jan David Mol
jjdmol at gmail.com
Sat May 19 12:19:01 CEST 2007
Hi,
I just finished obtaining VLC playback under wxPython on Mac. My
modifications may break other stuff and require some ugly hacks
(imho), but do get the job done. I like any advice on how to proceed
or fix these issues.
The process consists of two phases: getting the python bindings to
compile, and making them actually work. I'm maintaining a wiki entry
for myself (https://www.tribler.org/VlcMacHowto) which contains the
process, but I'll repeat the core of it here. Below is included a
description of what to patch in the source, how to compile/build, a
test.py file and the full patch I'm using.
Jan David
== Patches
The main action is in modules/gui/macosx/voutgl.m.
0) Include Carbon/Carbon.h.
1) VLC expects an AGLDrawable handle (in set_visual), which can be
obtained from a WindowRef. However, my patch chooses to let VLC
expect a ControlRef, as this provides VLC the knowledge of the
control bounds. A conversion is done by calling drawable =
GetWindowPort(GetControlOwner(controlref)).
2) the aglSwap routine swaps GL buffers to display a new frame, but
fails to inform Carbon that the window's content is invalidated and
should thus be redrawn. This can be fixed by calling:
WindowRef win;
Rect rect,clipBounds,viewBounds;
/* invalidate window data to force redraw */
win = GetWindowFromPort( p_vout->p_sys->agl_drawable );
GetControlBounds( p_vout->p_sys->theControl, &rect );
InvalWindowRect( win, &rect );
3) As set_viewport kept crashing on me, I added a b_viewport_set to
ignore any drawable-* viewport/clipping settings if they're all set
to 0, so VLC won't assume nothing is visible in that case.
4) finally, VLC needs to respond to window (control) resizing. As I
couldn't easily tell how to add a function to VLC which i can call
onResize, I decided to check for size changes every frame:
/* check for resizing -- ugly hack to do this in
aglSwap, i.e. every frame */
clipBounds = viewBounds = rect;
/* ignore consecutive viewport update with identical
parameters */
if( memcmp(&clipBounds, &(p_vout->p_sys->clipBounds),
sizeof(clipBounds) )
&& memcmp(&viewBounds, &(p_vout->p_sys->viewBounds),
sizeof(viewBounds)) )
{
/* set first to avoid infinite recursion */
p_vout->p_sys->clipBounds = clipBounds;
p_vout->p_sys->viewBounds = viewBounds;
aglSetViewport(p_vout, viewBounds, clipBounds);
aglReshape( p_vout );
}
== Compiling
To compile, I chose to make 'make install' work, as this allows the
use of 'vlc-config', on which the python bindings depend. This
requires the following patches, and sometimes a minor tweak more. A
simple search can easily locate them:
- don't use --enable-mediacontrol-python-bindings. It expects VLC to
be already make installed (chicken-egg?). go to bindings/python and
build them manually.
- remove VLC.app as an install target (remove "vlc_app_DATA =
VLC.app") as .app cannot be installed this way
- fix po/Makefile: it contains MKINSTALLDIRS = @MKINSTALLDIRS@, let
it point to any mkinstalldirs.
- fix vlc-config: clear cflags_tuning, it won't work when compiling
for i386 and PPC at once.
- fix vlc-config: remove -lvlc-control. it won't be built.
- after make install, install some missing libs vlc-config will point
to:
for i in `./vlc-config --target builtin`; do cp $i $PREFIX/lib/vlc/
`basename $i`; done
cp extras/contrib/vlc-lib/vlc_lib*.dylib $PREFIX/lib
To use the python bindings, do (test.py included below, add a
movie.mpg and install wxPython first):
export PYTHONPATH=$PREFIX/lib/python*/site-packages
export DYLD_LIBRARY_PATH=$PREFIX/lib/
python test.py
=== test.py
import vlc
import wx
class VideoWindow(wx.Window):
def __init__( self, parent ):
wx.Window.__init__( self, parent, -1 )
def play( self ):
self.video = vlc.MediaControl(["--verbose","2"])
self.video.set_visual( self.GetHandle() )
self.video.playlist_add_item("movie.mpg")
pos = vlc.Position()
pos.origin,pos.key,pos.value = vlc.AbsolutePosition,vlc.MediaTime,0
self.video.start(pos)
class VideoFrame(wx.Frame):
def __init__( self ):
wx.Frame.__init__( self, None, -1, "VLC playback test", size=
(800,600) )
sizer = wx.BoxSizer( wx.VERTICAL )
video = VideoWindow( self )
sizer.Add( video, 1, wx.EXPAND )
sizer.Add( wx.StaticText( self, -1, "foo" ), 0 )
self.SetSizer( sizer )
video.play()
class VideoApp(wx.App):
def OnInit(self):
VideoFrame().Show()
return True
VideoApp().MainLoop()
=== Patch
--- Makefile.orig 2007-05-16 15:49:03.000000000 +0200
+++ Makefile 2007-05-16 15:49:10.000000000 +0200
@@ -628,7 +628,6 @@
#noinst_DATA = vlc-bundle
# Create the MacOS X app
-vlc_app_DATA = VLC.app
vlc_appdir = $(bindir)
#DATA_win32_rc = $(noinst_share_vlc_win32_rc_DATA)
#noinst_share_vlc_win32_rc_DATA = share/vlc_win32_rc.$(OBJEXT)
--- po/Makefile.orig 2007-05-08 09:14:19.000000000 +0200
+++ po/Makefile 2007-05-08 09:14:50.000000000 +0200
@@ -26,7 +26,7 @@
INSTALL = /usr/bin/install -c
INSTALL_DATA = ${INSTALL} -m 644
-MKINSTALLDIRS = @MKINSTALLDIRS@
+MKINSTALLDIRS = autotools/mkinstalldirs
mkinstalldirs = $(SHELL) `case "$(MKINSTALLDIRS)" in /*) echo "$
(MKINSTALLDIRS)" ;; *) echo "$(top_builddir)/$(MKINSTALLDIRS)" ;; esac`
GMSGFMT = /Users/jandavidmol/svn/vlc-trunk/./extras/contrib/bin/msgfmt
--- vlc-config.orig 2007-05-16 15:48:00.000000000 +0200
+++ vlc-config 2007-05-16 15:48:13.000000000 +0200
@@ -20,7 +20,7 @@
objcflags=""
ldflags=""
-cflags_tuning="-march=pentium-m -mtune=prescott"
+cflags_tuning=""
cflags_optim=" -O3 -ffast-math -funroll-loops"
cflags_optim_nodebug=" -fomit-frame-pointer"
cflags_nooptim=" -O2"
@@ -822,7 +822,7 @@
;;
external)
echo_external=yes
- ldflags="${ldflags} -lvlc -lvlc-control"
+ ldflags="${ldflags} -lvlc"
;;
*)
module="$1"
Index: modules/gui/macosx/voutgl.m
===================================================================
--- modules/gui/macosx/voutgl.m (revision 20150)
+++ modules/gui/macosx/voutgl.m (working copy)
@@ -43,6 +43,7 @@
#include <OpenGL/gl.h>
#include <AGL/agl.h>
+#include <Carbon/Carbon.h>
/
************************************************************************
*****
* VLCGLView interface
@@ -68,11 +69,13 @@
vlc_bool_t b_embedded;
AGLContext agl_ctx;
AGLDrawable agl_drawable;
+ ControlRef theControl;
int i_offx, i_offy;
int i_width, i_height;
WindowRef theWindow;
WindowGroupRef winGroup;
vlc_bool_t b_clipped_out;
+ vlc_bool_t b_viewport_set;
Rect clipBounds, viewBounds;
};
@@ -470,7 +473,8 @@
Rect clipBounds;
var_Get( p_vout->p_libvlc, "drawable", &val );
- p_vout->p_sys->agl_drawable = (AGLDrawable)val.i_int;
+ p_vout->p_sys->theControl = val.i_int;
+ p_vout->p_sys->agl_drawable = (AGLDrawable)GetWindowPort
(GetControlOwner(val.i_int));
aglSetDrawable(p_vout->p_sys->agl_ctx, p_vout->p_sys-
>agl_drawable);
var_Get( p_vout->p_libvlc, "drawable-view-top", &val );
@@ -492,7 +496,9 @@
p_vout->p_sys->b_clipped_out = (clipBounds.top ==
clipBounds.bottom)
|| (clipBounds.left ==
clipBounds.right);
- if( ! p_vout->p_sys->b_clipped_out )
+ p_vout->p_sys->b_viewport_set = viewBounds.top || viewBounds.bottom
+ || viewBounds.left ||
viewBounds.right;
+ if( !p_vout->p_sys->b_clipped_out && p_vout->p_sys-
>b_viewport_set )
{
aglLock(p_vout);
aglSetViewport(p_vout, viewBounds, clipBounds);
@@ -590,7 +596,8 @@
Rect clipBounds;
var_Get( p_vout->p_libvlc, "drawable", &val );
- p_vout->p_sys->agl_drawable = (AGLDrawable)val.i_int;
+ p_vout->p_sys->theControl = val.i_int;
+ p_vout->p_sys->agl_drawable = (AGLDrawable)GetWindowPort
(GetControlOwner(val.i_int));
aglSetDrawable(p_vout->p_sys->agl_ctx, p_vout->p_sys-
>agl_drawable);
var_Get( p_vout->p_libvlc, "drawable-view-top", &val );
@@ -714,7 +721,9 @@
p_vout->p_sys->b_clipped_out = (clipBounds.top ==
clipBounds.bottom)
|| (clipBounds.left ==
clipBounds.right);
- if( ! p_vout->p_sys->b_clipped_out )
+ p_vout->p_sys->b_viewport_set = viewBounds.top ||
viewBounds.bottom
+ || viewBounds.left ||
viewBounds.right;
+ if( !p_vout->p_sys->b_clipped_out )
{
/* ignore consecutive viewport update with
identical parameters */
if( memcmp(&clipBounds, &(p_vout->p_sys-
>clipBounds), sizeof(clipBounds) )
@@ -769,10 +778,36 @@
static void aglSwap( vout_thread_t * p_vout )
{
- if( ! p_vout->p_sys->b_clipped_out )
+ if( !p_vout->p_sys->b_clipped_out || !p_vout->p_sys-
>b_viewport_set )
{
p_vout->p_sys->b_got_frame = VLC_TRUE;
aglSwapBuffers(p_vout->p_sys->agl_ctx);
+
+ if( !p_vout->p_sys->b_viewport_set ) {
+ WindowRef win;
+ Rect rect,clipBounds,viewBounds;
+
+ /* invalidate window data to force redraw */
+ win = GetWindowFromPort( p_vout->p_sys->agl_drawable );
+ //GetWindowPortBounds( win, &rect );
+ GetControlBounds( p_vout->p_sys->theControl, &rect );
+ InvalWindowRect( win, &rect );
+
+ /* check for resizing -- ugly hack to do this in
aglSwap, i.e. every frame */
+ clipBounds = viewBounds = rect;
+
+ /* ignore consecutive viewport update with identical parameters */
+ if( memcmp(&clipBounds, &(p_vout->p_sys->clipBounds), sizeof
(clipBounds) )
+ && memcmp(&viewBounds, &(p_vout->p_sys->viewBounds), sizeof
(viewBounds)) )
+ {
+ /* set first to avoid infinite recursion */
+ p_vout->p_sys->clipBounds = clipBounds;
+ p_vout->p_sys->viewBounds = viewBounds;
+
+ aglSetViewport(p_vout, viewBounds, clipBounds);
+ aglReshape( p_vout );
+ }
+ }
}
else
{
--
This is the vlc-devel mailing-list, see http://www.videolan.org/vlc/
To unsubscribe, please read http://developers.videolan.org/lists.html
More information about the vlc-devel
mailing list