[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