Merge bindings to trunk
authorClément Stenac <zorglub@videolan.org>
Wed, 1 Jun 2005 22:19:03 +0000 (22:19 +0000)
committerClément Stenac <zorglub@videolan.org>
Wed, 1 Jun 2005 22:19:03 +0000 (22:19 +0000)
19 files changed:
bindings/STATUS [new file with mode: 0644]
bindings/java-gcj/AUTHORS [new file with mode: 0644]
bindings/java-gcj/JVLC.java [new file with mode: 0644]
bindings/java-gcj/JVLCBoolVariable.java [new file with mode: 0644]
bindings/java-gcj/JVLCFloatVariable.java [new file with mode: 0644]
bindings/java-gcj/JVLCIntVariable.java [new file with mode: 0644]
bindings/java-gcj/JVLCStringVariable.java [new file with mode: 0644]
bindings/java-gcj/JVLCTimeVariable.java [new file with mode: 0644]
bindings/java-gcj/JVLCVarValue.java [new file with mode: 0644]
bindings/java-gcj/JVLCVarVariable.java [new file with mode: 0644]
bindings/java-gcj/JVLCVariable.java [new file with mode: 0644]
bindings/java-gcj/Makefile [new file with mode: 0644]
bindings/java-gcj/README [new file with mode: 0644]
bindings/java-gcj/VlcClient.java [new file with mode: 0644]
bindings/java-gcj/vlc-glue.cc [new file with mode: 0644]
bindings/python/Makefile [new file with mode: 0644]
bindings/python/setup.py [new file with mode: 0644]
bindings/python/vlcdebug.py [new file with mode: 0644]
bindings/python/vlcglue.c [new file with mode: 0644]

diff --git a/bindings/STATUS b/bindings/STATUS
new file mode 100644 (file)
index 0000000..28f0227
--- /dev/null
@@ -0,0 +1,34 @@
+###########################
+# STATUS for VLC bindings #
+###########################
+
+* General
+---------
+  * TODO
+     - Integrate bindings creation with build system
+
+* API
+-----
+  * TODO
+     - Clean up / Use VLC coding styles
+     - VLM control
+
+* Python: (Olivier Aubert) 
+---------
+  * Implements the mediacontrol API
+  * TODO
+     - Fix win32 build
+     - Clean up glue file
+
+* Java:   (Filippo Carone)
+-------
+  * Implements libvlc base API
+  * Only works with gcj
+  * TODO
+     - Fix crash with command line arguments
+     - Implement mediacontrol
+     - provide "make install" 
+
+* .NET:   (jlj)
+-------  
+  * Not commited yet :)
diff --git a/bindings/java-gcj/AUTHORS b/bindings/java-gcj/AUTHORS
new file mode 100644 (file)
index 0000000..204ac98
--- /dev/null
@@ -0,0 +1 @@
+Filippo Carone <filippo[dontspam]@carone.org>
diff --git a/bindings/java-gcj/JVLC.java b/bindings/java-gcj/JVLC.java
new file mode 100644 (file)
index 0000000..de47923
--- /dev/null
@@ -0,0 +1,100 @@
+/*****************************************************************************
+ * JVLC.java: global class for vlc Java Bindings
+ *****************************************************************************
+ * Copyright (C) 1998-2004 VideoLAN
+ *
+ * Authors: Filippo Carone <filippo@carone.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
+ * GNU General Public License for more details.
+ *
+ * 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.
+ *****************************************************************************/
+
+public class JVLC {
+
+    private int id;
+
+    public JVLC(String[] args) {
+       String[] properArgs = new String[args.length + 1];
+       properArgs[0] = "jvlc";
+       for (int i = 0; i < args.length; i++)
+           properArgs[i+1] = args[i];
+
+       this.id = create();
+       init(properArgs);
+    }
+
+    private native int create();
+
+    private native int init(String[] args);
+
+    public native int addInterface(String moduleName, boolean blocking, boolean startPlay);
+
+    public int addInterface(boolean blocking, boolean startPlay) {
+       return addInterface(null, blocking, startPlay);
+    }
+
+    public native String getVersion();
+
+    public native String getError(int errorCode);
+
+    public native int die();
+
+    public native int cleanUp();
+    
+    public native int setVariable(JVLCVariable jvlcVariable);
+
+    public native JVLCVariable getVariable(String varName); // XXX in progress
+
+    public native int addTarget(String URI, String[] options, int insertMode, int position);
+
+    public native int play();
+   
+    public native int pause();
+
+    public native int stop();
+
+    public native boolean isPlaying();
+
+    public native float getPosition();
+
+    public native float setPosition(float position);
+
+    public native int getTime();
+
+    public native int setTime(int seconds, boolean relative);
+
+    public native int getLength();
+
+    public native float speedFaster();
+
+    public native float speedSlower();
+
+    public native int getPlaylistIndex();
+
+    public native int getPlaylistItems();
+
+    public native int playlistNext();
+
+    public native int playlistPrev();
+
+    public native int playlistClear();
+
+    public native int getVolume();
+
+    public native int setVolume(int volume);
+
+    public native int muteVolume();
+
+    public native int fullScreen();
+}
diff --git a/bindings/java-gcj/JVLCBoolVariable.java b/bindings/java-gcj/JVLCBoolVariable.java
new file mode 100644 (file)
index 0000000..3230ad7
--- /dev/null
@@ -0,0 +1,13 @@
+public class JVLCBoolVariable extends JVLCVariable {
+
+    public JVLCBoolVariable(String name, int value) {
+       super(name);
+       if (value != 0) this.value = new Integer(1);
+       else this.value = new Integer(0);
+    }
+
+    public int getBoolValue() {
+       return ((Integer)value).intValue();
+    }
+
+}
diff --git a/bindings/java-gcj/JVLCFloatVariable.java b/bindings/java-gcj/JVLCFloatVariable.java
new file mode 100644 (file)
index 0000000..c1de950
--- /dev/null
@@ -0,0 +1,12 @@
+public class JVLCFloatVariable extends JVLCVariable {
+
+    public JVLCFloatVariable(String name, float value) {
+       super(name);
+       this.value = new Float(value);
+    }
+
+    public float getFloatValue() {
+       return ((Float)value).floatValue();
+    }
+
+}
diff --git a/bindings/java-gcj/JVLCIntVariable.java b/bindings/java-gcj/JVLCIntVariable.java
new file mode 100644 (file)
index 0000000..e582e87
--- /dev/null
@@ -0,0 +1,13 @@
+public class JVLCIntVariable extends JVLCVariable {
+
+
+    public JVLCIntVariable(String name, int value) {
+       super(name);
+       this.value = new Integer(value);
+    }
+
+    public int getIntValue() {
+       return ((Integer)value).intValue();
+    }
+
+}
diff --git a/bindings/java-gcj/JVLCStringVariable.java b/bindings/java-gcj/JVLCStringVariable.java
new file mode 100644 (file)
index 0000000..9d3b7b8
--- /dev/null
@@ -0,0 +1,12 @@
+public class JVLCStringVariable extends JVLCVariable {
+
+    public JVLCStringVariable(String name, String value) {
+       super(name);
+       this.value = value;
+    }
+
+    public String getStringValue() {
+       return (String)value;
+    }
+
+}
diff --git a/bindings/java-gcj/JVLCTimeVariable.java b/bindings/java-gcj/JVLCTimeVariable.java
new file mode 100644 (file)
index 0000000..3486e6f
--- /dev/null
@@ -0,0 +1,12 @@
+public class JVLCTimeVariable extends JVLCVariable {
+
+    public JVLCTimeVariable(String name, long value) {
+       super(name);
+       this.value = new Long(value);
+    }
+
+    public long getTimeValue() {
+       return ((Long)value).longValue();
+    }
+
+}
diff --git a/bindings/java-gcj/JVLCVarValue.java b/bindings/java-gcj/JVLCVarValue.java
new file mode 100644 (file)
index 0000000..46ee141
--- /dev/null
@@ -0,0 +1,19 @@
+public class JVLCVarValue {
+    
+    String name;
+    int OID;
+    
+    public JVLCVarValue(String name, int OID) {
+       this.name = name;
+       this.OID = OID;
+    }
+
+    public String getName() {
+       return name;
+    }
+
+    public int getOID() {
+       return OID;
+    }
+
+}
diff --git a/bindings/java-gcj/JVLCVarVariable.java b/bindings/java-gcj/JVLCVarVariable.java
new file mode 100644 (file)
index 0000000..a00074f
--- /dev/null
@@ -0,0 +1,12 @@
+public class JVLCVarVariable extends JVLCVariable {
+
+    public JVLCVarVariable(String name, JVLCVarValue value) {
+       super(name);
+       this.value = value;
+    }
+
+    public JVLCVarValue getVarValue() {
+       return (JVLCVarValue)value;
+    }
+
+}
diff --git a/bindings/java-gcj/JVLCVariable.java b/bindings/java-gcj/JVLCVariable.java
new file mode 100644 (file)
index 0000000..b37028f
--- /dev/null
@@ -0,0 +1,21 @@
+public abstract class JVLCVariable {
+    String name;
+    Object value;
+
+    public JVLCVariable(String name) {
+       this.name = name;
+    }
+
+    public String getName() {
+       return name;
+    }
+
+    public Object getValue() {
+       return value;
+    }
+
+    public void setValue(Object value) {
+       this.value = value;
+    }
+       
+}
diff --git a/bindings/java-gcj/Makefile b/bindings/java-gcj/Makefile
new file mode 100644 (file)
index 0000000..7793998
--- /dev/null
@@ -0,0 +1,28 @@
+OBJECTS = VlcClient.o JVLC.o JVLCVariable.o JVLCVarValue.o JVLCVarVariable.o JVLCIntVariable.o JVLCTimeVariable.o JVLCStringVariable.o JVLCFloatVariable.o JVLCBoolVariable.o vlc-glue.o
+FLAGS = -I. -I/usr/local/include/vlc -L../../lib -lvlc `top_builddir=../.. ../../vlc-config --libs vlc builtin extern` `top_builddir=../.. ../../vlc-config --cxxflags` --main=VlcClient
+JHEADERS = JVLC.h JVLCVariable.h JVLCIntVariable.h JVLCBoolVariable.h JVLCTimeVariable.h JVLCStringVariable.h JVLCFloatVariable.h JVLCVarVariable.h JVLCVarValue.h
+JCC=gcj
+CXX=g++
+JCH=gcjh
+DEBUG=-g
+
+VlcClient: $(OBJECTS)
+       $(JCC) -o jvlc -I. $(OBJECTS) $(DEBUG) $(FLAGS)
+
+VlcClient.class: VlcClient.java
+       $(JCC) $(DEBUG) -C VlcClient.java
+
+%.o: %.class
+       $(JCC) $(DEBUG) -c $?
+
+%.class: %.java
+       $(JCC) $(DEBUG) -C $?
+
+%.h: %.class
+       $(JCH) $(*F)
+
+vlc-glue.o: $(JHEADERS) vlc-glue.cc
+       $(CXX) $(DEBUG) -I./ -c vlc-glue.cc
+
+clean:
+       rm -f jvlc *.o *.class $(JHEADERS) *~
diff --git a/bindings/java-gcj/README b/bindings/java-gcj/README
new file mode 100644 (file)
index 0000000..2c58511
--- /dev/null
@@ -0,0 +1,10 @@
+Implementation Notes
+--------------------
+
+ The union vlc_value_t has been implemented as a hierarchy of classes
+which has JVLCVariable.class as the root. All the children of this
+class are named JVLC<type>Variable.class and are mapped 1:1 to the
+union members with some exceptions: p_address is not implemented since
+there's no notion of address in Java, vlc_object_t is not implemented
+since I don't know how to represent it in Java and is not defined in
+vlc/vlc.h 
\ No newline at end of file
diff --git a/bindings/java-gcj/VlcClient.java b/bindings/java-gcj/VlcClient.java
new file mode 100644 (file)
index 0000000..c52bc18
--- /dev/null
@@ -0,0 +1,12 @@
+public class VlcClient {
+
+    public static void main(String[] args) {
+
+       JVLC vlc = new JVLC(args);
+       System.out.println(vlc.getVersion());
+       vlc.addInterface(true, true);
+       vlc.die();
+       vlc.cleanUp();
+    }
+
+}
diff --git a/bindings/java-gcj/vlc-glue.cc b/bindings/java-gcj/vlc-glue.cc
new file mode 100644 (file)
index 0000000..826cb91
--- /dev/null
@@ -0,0 +1,300 @@
+/* These are a must*/
+#include <gcj/cni.h>
+#include <vlc/vlc.h>
+
+#include <stdio.h> // for printf
+#include <stdlib.h> // for calloc
+
+/* JVLC internal imports, generated by gcjh */
+#include "JVLC.h"
+#include "JVLCVariable.h"
+#include "JVLCIntVariable.h"
+#include "JVLCBoolVariable.h"
+#include "JVLCFloatVariable.h"
+#include "JVLCStringVariable.h"
+#include "JVLCTimeVariable.h"
+#include "JVLCVarVariable.h"
+#include "JVLCVarValue.h"
+
+/* Java classes used throughout here */
+#include <java/lang/String.h>
+#include <java/lang/Class.h>
+#include <java/lang/System.h>
+#include <java/io/PrintStream.h>
+
+void setString(jstring orig, char* dest);
+
+jint JVLC::create () {
+  return VLC_Create();
+}
+
+jint JVLC::init(JArray< ::java::lang::String *> *args) {
+
+  int argc = 0;
+  char* arguments[argc];
+
+  if (args != NULL) // It's a very bad day otherwise
+  {
+    argc = args->length;
+    arguments[argc];
+
+    /*
+     * convert the JArray<String*>*  in char**
+     * so in a way suitable for VLC_Init
+     */
+    jstring* argsElements = elements(args);
+
+    for (int i = 0; i < argc; i++) {
+      arguments[i] = (char*) malloc(JvGetStringUTFLength(argsElements[i]) + 1);
+      setString(argsElements[i], arguments[i]);
+    }
+  }
+
+  return VLC_Init(this->id, argc, arguments);
+}
+
+
+jint JVLC::addInterface(java::lang::String* moduleName, jboolean blocking, jboolean startPlay) {
+
+  char* psz_module = NULL;
+  if (moduleName != NULL) {
+    psz_module = (char *) malloc(JvGetStringUTFLength(moduleName));
+    setString(moduleName, psz_module);
+  }
+
+  int i_blocking = 0;
+  int i_startPlay = 0;
+  if (blocking) i_blocking = 1;
+  if (startPlay) i_startPlay = 1;
+
+  int addIntf_res = VLC_AddIntf(this->id, (char* const) psz_module, i_blocking, i_startPlay);
+  
+  if (psz_module != NULL)
+    free(psz_module);
+  
+  return addIntf_res;
+
+}
+
+
+jstring JVLC::getVersion() {
+  return JvNewStringUTF(VLC_Version());
+}
+
+
+jstring JVLC::getError(jint errorCode) {
+  return JvNewStringUTF(VLC_Error(errorCode));
+}
+
+
+jint JVLC::die() {
+  return VLC_Die(this->id);
+}
+
+
+jint JVLC::cleanUp() {
+  return VLC_CleanUp(this->id);
+}
+
+
+jint JVLC::setVariable(::JVLCVariable *jvlcVariable) {
+
+  /* these are the two parameters given the the
+   * VLC_VariableSet() function
+   */
+  vlc_value_t value;
+  char* psz_var = NULL;
+
+  if (jvlcVariable != NULL) {
+    jclass variableClass = jvlcVariable->getClass();
+
+    /* We use the class name for kinda of instanceof */
+    jstring className = variableClass->getName();
+
+    /**
+     * VLC_SetVariable takes a union as its second argument.
+     * The union members are mapped 1:1 to java types which
+     * extend JVLCVariable. So here we check the runtime type
+     * of the actual variable and act consequently. Here is the
+     * mapping:
+     *
+     * typedef union
+     *{
+     * int             i_int;      JVLCIntVariable
+     * vlc_bool_t      b_bool;     JVLCBoolVariable
+     * float           f_float;    JVLCFloatVariable
+     * char *          psz_string; JVLCStringVariable
+     * void *          p_address;  -- NOT IMPLEMENTED --
+     * vlc_object_t *  p_object;   -- NOT IMPLEMENTED --
+     * vlc_list_t *    p_list;     JVLCListVariable XXX:TODO
+     * signed long long i_time;    JVLCTimeVariable
+     * struct { char *psz_name; int i_object_id; } var; JVLCVarVariable <- this name sucks
+     * // Make sure the structure is at least 64bits
+     * struct { char a, b, c, d, e, f, g, h; } padding; <- Do we really need this?
+     *
+     * } vlc_value_t;
+     */
+
+    /* i_int */
+    if (className->equals(JvNewStringUTF("VLCIntVariable" ))) {
+      value.i_int = ((::JVLCIntVariable *)jvlcVariable)->getIntValue();
+    }
+    /* b_bool */
+    else if (className->equals(JvNewStringUTF("VLCBoolVariable"))) {
+      value.b_bool = ((::JVLCBoolVariable *)jvlcVariable)->getBoolValue();
+    } 
+    /* f_float */
+    else if (className->equals(JvNewStringUTF("VLCFloatVariable"))) {
+      value.f_float = ((::JVLCFloatVariable *)jvlcVariable)->getFloatValue();
+    }
+    /* psz_string */
+    else if (className->equals(JvNewStringUTF("VLCStringVariable"))) {
+      value.psz_string = (char* const) elements((((::JVLCStringVariable *)jvlcVariable)->getStringValue())->toCharArray());
+    }
+    /* i_time */
+    else if (className->equals(JvNewStringUTF("VLCTimeVariable"))) {
+      value.i_time = ((::JVLCTimeVariable *)jvlcVariable)->getTimeValue();
+    }
+
+    /* var */
+    else if (className->equals(JvNewStringUTF("VLCVarVariable"))) {
+      jstring varValueName = ((::JVLCVarVariable *)jvlcVariable)->getVarValue()->getName();
+      value.var.psz_name = (char *) malloc(JvGetStringUTFLength(varValueName));
+      setString(varValueName, value.var.psz_name);
+      value.var.i_object_id = (((::JVLCVarVariable *)jvlcVariable)->getVarValue())->getOID();
+    }
+    psz_var = (char *) malloc(JvGetStringUTFLength(jvlcVariable->getName()));
+    setString(jvlcVariable->getName(), psz_var);
+  }
+  
+  return VLC_VariableSet(this->id, (char* const) psz_var, value);
+
+}
+
+jint JVLC::addTarget(::java::lang::String *URI, JArray< ::java::lang::String *> *options, jint insertMode, jint position) {
+
+  char*  psz_target   = NULL;
+  char** ppsz_options = NULL;
+  int options_number = 0;
+  
+  if (URI != NULL) {
+    psz_target = (char *) malloc( JvGetStringUTFLength(URI));
+    setString(URI, psz_target);
+  }
+
+  if (options != NULL) {
+    options_number = options->length;
+    ppsz_options[options_number];
+    jstring* jstr_options = elements(options);
+
+    for (jint i = 0; i < options_number; i++) {
+      ppsz_options[i] = (char *) malloc(JvGetStringUTFLength(jstr_options[i]));
+      setString(jstr_options[i], ppsz_options[i]);
+    }
+  }
+  
+  return VLC_AddTarget(this->id, (char const *)psz_target, (const char **) ppsz_options, options_number, insertMode, position);
+}
+
+jint JVLC::play() {
+  return VLC_Play(this->id);
+}
+
+jint JVLC::pause() {
+  return VLC_Pause(this->id);
+}
+
+jint JVLC::stop() {
+  return VLC_Stop(this->id);
+}
+
+jboolean JVLC::isPlaying() {
+  return VLC_IsPlaying(this->id);
+}
+
+jfloat JVLC::getPosition() {
+  return VLC_PositionGet(this->id);
+}
+
+jfloat JVLC::setPosition(jfloat position) {
+  return VLC_PositionSet(this->id, position);
+}
+
+jint JVLC::getTime() {
+  return VLC_TimeGet(this->id);
+}
+
+jint JVLC::setTime(jint seconds, jboolean relative) {
+  return VLC_TimeSet(this->id, seconds, relative);
+}
+
+jint JVLC::getLength() {
+  return VLC_LengthGet(this->id);
+}
+
+jfloat JVLC::speedFaster() {
+  return VLC_SpeedFaster(this->id);
+}
+
+jfloat JVLC::speedSlower() {
+  return VLC_SpeedSlower(this->id);
+}
+
+jint JVLC::getPlaylistIndex() {
+  return VLC_PlaylistIndex(this->id);
+}
+
+jint JVLC::getPlaylistItems() {
+  return VLC_PlaylistNumberOfItems(this->id);
+}
+
+jint JVLC::playlistNext() {
+  return VLC_PlaylistNext(this->id);
+}
+
+jint JVLC::playlistPrev() {
+  return VLC_PlaylistPrev(this->id);
+}
+
+jint JVLC::playlistClear() {
+  return VLC_PlaylistClear(this->id);
+}
+
+jint JVLC::setVolume(jint volume) {
+  return VLC_VolumeSet(this->id, volume);
+}
+
+jint JVLC::getVolume() {
+  return VLC_VolumeGet(this->id);
+}
+
+jint JVLC::muteVolume() {
+  return VLC_VolumeMute(this->id);
+}
+
+jint JVLC::fullScreen() {
+  return VLC_FullScreen(this->id);
+}
+
+
+/* XXX: in progress */
+::JVLCVariable* JVLC::getVariable(::java::lang::String* varName) {
+
+  char* const psz_var = (char* const) elements( varName->toCharArray());
+  vlc_value_t value;
+  if (VLC_VariableGet(this->id, psz_var, &value) != VLC_SUCCESS) {
+    // throw exception
+    return NULL;
+  }
+  return NULL;
+}
+
+/*
+ * This is an helper function to convert jstrings to char*s
+ * setString _assumes_ the char* dest has been allocated
+ * XXX: should return >= 0 on success, < 0 on error
+ */
+void setString(jstring orig, char* dest) {
+  jsize chars = JvGetStringUTFRegion(orig, 0, orig->length(), dest);
+  dest[chars] = '\0';
+}
diff --git a/bindings/python/Makefile b/bindings/python/Makefile
new file mode 100644 (file)
index 0000000..f057af7
--- /dev/null
@@ -0,0 +1,15 @@
+ifdef HOMEDRIVE
+       COMPILERARG = --compiler=mingw32
+else
+       COMPILERARG = 
+endif
+
+all:
+       python setup.py build $(COMPILERARG)
+
+install:
+       python setup.py install
+
+clean:
+       $(RM) -rf build
+
diff --git a/bindings/python/setup.py b/bindings/python/setup.py
new file mode 100644 (file)
index 0000000..66bdf31
--- /dev/null
@@ -0,0 +1,86 @@
+from distutils.core import setup, Extension
+import os
+
+def get_vlcconfig():
+    vlcconfig=None
+    for n in ( 'vlc-config',
+               os.path.sep.join( ('..', '..', 'vlc-config' ))):
+        if os.path.exists(n):
+            vlcconfig=n
+            break
+    if vlcconfig is None:
+        print "*** Warning *** Cannot find vlc-config"
+    elif os.sys.platform == 'win32':
+        # Win32 does not know how to invoke the shell itself.
+        vlcconfig="sh %s" % vlcconfig
+    return vlcconfig
+
+def get_cflags():
+    vlcconfig=get_vlcconfig()
+    if vlcconfig is None:
+        return []
+    else:
+        cflags=os.popen('%s --cflags' % vlcconfig, 'r').readline().rstrip().split()
+        return cflags
+
+def get_ldflags():
+    vlcconfig=get_vlcconfig()
+    if vlcconfig is None:
+        return []
+    else:
+       os.environ['top_builddir'] = '../..'
+        ldflags=os.popen('%s --libs vlc builtin' % vlcconfig, 'r').readline().rstrip().split()
+        return ldflags
+
+# To compile in a local vlc tree
+vlclocal = Extension('vlc',
+                sources = ['vlcglue.c', '../../src/control/init.c'],
+                include_dirs = ['../../include', '../../', '/usr/win32/include' ],
+                extra_objects = [ '../../lib/libvlc.a' ],
+                extra_compile_args = get_cflags(),
+               extra_link_args = [ '-L../..' ]  + get_ldflags(),
+                )
+
+setup (name = 'MediaControl',
+       version = '0.8.2-1',
+       scripts = [ 'vlcdebug.py' ],
+       description = """VLC bindings for python.
+
+This module provides a MediaControl object, which implements an API
+inspired from the OMG Audio/Video Stream 1.0 specification. Moreover,
+the module provides a Object type, which gives a low-level access to
+the vlc objects and their variables.
+
+Example session:
+
+import vlc
+mc=vlc.MediaControl(['--verbose', '1'])
+mc.playlist_add_item('movie.mpg')
+
+# Start the movie at 2000ms
+p=vlc.Position()
+p.origin=vlc.RelativePosition
+p.key=vlc.MediaTime
+p.value=2000
+mc.start(p)
+# which could be abbreviated as
+# mc.start(2000)
+# for the default conversion from int is to make a RelativePosition in MediaTime
+
+# Display some text during 2000ms
+mc.display_text('Some useless information', 0, 2000)
+
+# Pause the video
+mc.pause(0)
+
+# Get status information
+mc.get_stream_information()
+
+# Access lowlevel objets
+o=vlc.Object(1)
+o.info()
+i=o.find_object('input')
+i.list()
+i.get('time')
+       """,
+       ext_modules = [ vlclocal ])
diff --git a/bindings/python/vlcdebug.py b/bindings/python/vlcdebug.py
new file mode 100644 (file)
index 0000000..b5524bd
--- /dev/null
@@ -0,0 +1,66 @@
+"""Wrapper around vlc module in order to ease the use of vlc.Object
+class (completion in ipython, access variable as attributes, etc).
+"""
+import vlc
+
+class VLCObject(object):
+    def __init__(self, id):
+        object.__setattr__(self, '_o', vlc.Object(id))
+
+    def find(self, typ):
+        t=self._o.find_object(typ)
+        if t is not None:
+            return VLCObject(t.info()['object-id'])
+        else:
+            return None
+
+    def __str__(self):
+        i=self._o.info()
+        return "VLCObject %d (%s) : %s" % (i['object-id'],
+                                           i['object-type'],
+                                           i['object-name'])
+
+    def tree(self, prefix=" "):
+        """Displays the children as a tree."""
+        print prefix, self
+        for i in self._o.children():
+            t=VLCObject(i)
+            t.tree(prefix=prefix + " ")
+        return
+
+    def __getattribute__(self, attr):
+        #print "Getting %s" % attr
+        if attr == '__members__':
+            o=object.__getattribute__(self, '_o')
+            l=dir(o)
+            l.extend([ n.replace('-','_') for n in o.list() ])
+            return l
+        try:
+            return object.__getattribute__ (self, attr)
+        except AttributeError, e:
+            try:
+                return self._o.__getattribute__ (attr)
+            except AttributeError, e:
+                attr=attr.replace('_', '-')
+                if attr in self._o.list():
+                    return self._o.get(attr)
+                else:
+                    raise e
+
+    def __setattr__(self, name, value):
+        n=name.replace('_', '-')
+        if n in self._o.list():
+            self._o.set(n, value)
+        else:
+            object.__setattr__(self, name, value)
+
+#mc=vlc.MediaControl()
+#mc.playlist_add_item('/tmp/k.mpg')
+#mc.start(0)
+
+def test():
+    global mc,o
+    mc=vlc.MediaControl()
+    mc.playlist_add_item('/tmp/k.mpg')
+    mc.start(0)
+    o=VLCObject(0)
diff --git a/bindings/python/vlcglue.c b/bindings/python/vlcglue.c
new file mode 100644 (file)
index 0000000..d966899
--- /dev/null
@@ -0,0 +1,1342 @@
+#include <Python.h>
+#include "structmember.h"
+
+/* Undefine the following define to disable low-level vlc Object support */
+#define VLCOBJECT_SUPPORT 1
+
+#define __VLC__
+
+#include <stdio.h>
+
+#include <vlc/control.h>
+
+#define SELF ((MediaControl*)self)
+
+#define MC_TRY exception=mediacontrol_exception_init(exception)
+#define MC_EXCEPT  \
+  if (exception->code) { \
+    PyObject *py_exc = MediaControl_InternalException; \
+    switch (exception->code) { \
+    case mediacontrol_InternalException: \
+      py_exc = MediaControl_InternalException; \
+      break; \
+    case mediacontrol_PlaylistException: \
+      py_exc = MediaControl_PlaylistException; \
+      break; \
+    case mediacontrol_InvalidPosition: \
+      py_exc = MediaControl_InvalidPosition; \
+      break; \
+    case mediacontrol_PositionKeyNotSupported: \
+      py_exc = MediaControl_PositionKeyNotSupported; \
+      break; \
+    case mediacontrol_PositionOriginNotSupported: \
+      py_exc = MediaControl_PositionOriginNotSupported; \
+      break; \
+    } \
+    PyErr_SetString(py_exc, exception->message); \
+    mediacontrol_exception_free(exception); \
+    return NULL; \
+  } else { mediacontrol_exception_free(exception); }
+
+/* Module globals */
+static PyObject *MediaControl_InternalException          = NULL;
+static PyObject *MediaControl_PositionKeyNotSupported    = NULL;
+static PyObject *MediaControl_PositionOriginNotSupported = NULL;
+static PyObject *MediaControl_InvalidPosition            = NULL;
+static PyObject *MediaControl_PlaylistException          = NULL;
+
+
+#ifdef VLCOBJECT_SUPPORT
+
+/* vlcObject (low level access) */
+#define VLCSELF ((vlcObject*)self)
+typedef struct {
+  PyObject_HEAD
+  vlc_object_t* p_object;
+} vlcObject;
+
+staticforward PyTypeObject vlcObject_Type;
+
+#endif
+
+/* MediaControl object */
+typedef struct {
+  PyObject_HEAD
+  mediacontrol_Instance* mc;
+} MediaControl;
+
+staticforward PyTypeObject MediaControl_Type;
+
+/* Position object */
+typedef struct {
+  PyObject_HEAD
+  int origin;
+  int key;
+  long long value;
+} PyPosition;
+
+static int
+PyPosition_init(PyPosition *self, PyObject *args, PyObject *kwds)
+{
+  self->origin = mediacontrol_AbsolutePosition;
+  self->key    = mediacontrol_MediaTime;
+  self->value  = 0;
+
+  return 0;
+}
+
+static PyMethodDef PyPosition_methods[] = {
+    {NULL}  /* Sentinel */
+};
+
+static PyMemberDef PyPosition_members[] = {
+  {"origin", T_INT, offsetof(PyPosition, origin), 0, "Position origin"},
+  {"key",    T_INT, offsetof(PyPosition, key),    0, "Position key"},
+  {"value",  T_ULONG, offsetof(PyPosition, value), 0, "Position value"},
+  {NULL}  /* Sentinel */
+};
+
+static PyTypeObject PyPosition_Type = {
+    PyObject_HEAD_INIT(NULL)
+    0,                         /*ob_size*/
+    "vlc.Position",            /*tp_name*/
+    sizeof(PyPosition_Type),   /*tp_basicsize*/
+    0,                         /*tp_itemsize*/
+    0,                         /*tp_dealloc*/
+    0,                         /*tp_print*/
+    0,                         /*tp_getattr*/
+    0,                         /*tp_setattr*/
+    0,                         /*tp_compare*/
+    0,                         /*tp_repr*/
+    0,                         /*tp_as_number*/
+    0,                         /*tp_as_sequence*/
+    0,                         /*tp_as_mapping*/
+    0,                         /*tp_hash */
+    0,                         /*tp_call*/
+    0,                         /*tp_str*/
+    0,                         /*tp_getattro*/
+    0,                         /*tp_setattro*/
+    0,                         /*tp_as_buffer*/
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
+    "Represent a Position with origin, key and value",  /* tp_doc */
+    0,                        /* tp_traverse */
+    0,                        /* tp_clear */
+    0,                        /* tp_richcompare */
+    0,                        /* tp_weaklistoffset */
+    0,                        /* tp_iter */
+    0,                        /* tp_iternext */
+    PyPosition_methods,             /* tp_methods */
+    PyPosition_members,             /* tp_members */
+    0,                         /* tp_getset */
+    0,                         /* tp_base */
+    0,                         /* tp_dict */
+    0,                         /* tp_descr_get */
+    0,                         /* tp_descr_set */
+    0,                         /* tp_dictoffset */
+    (initproc)PyPosition_init, /* tp_init */
+    0,                         /* tp_alloc */
+    0,                         /* tp_new */
+};
+
+static mediacontrol_PositionKey positionKey_py_to_c( PyObject * py_key )
+{
+    mediacontrol_PositionKey key_position = mediacontrol_MediaTime;
+    int key;
+
+    if(!PyArg_Parse(py_key, "i", &key))
+      {
+       PyErr_SetString (MediaControl_InternalException, "Invalid key value"); 
+       return key_position;
+      }
+
+    switch (key)
+    {
+       case 0: key = mediacontrol_ByteCount;   break;
+       case 1: key = mediacontrol_SampleCount; break;
+       case 2: key = mediacontrol_MediaTime;   break;
+    } 
+
+    return key_position;
+}
+
+static mediacontrol_PositionOrigin positionOrigin_py_to_c( PyObject * py_origin )
+{
+    mediacontrol_PositionOrigin  origin_position = mediacontrol_AbsolutePosition;
+    int origin;
+    
+    if(!PyArg_Parse(py_origin,"i", &origin))
+      {
+       PyErr_SetString (MediaControl_InternalException, "Invalid origin value"); 
+       return origin_position;
+      }
+
+    switch (origin)
+    {
+       case 0: origin_position = mediacontrol_AbsolutePosition; break;
+       case 1: origin_position = mediacontrol_RelativePosition; break;
+       case 2: origin_position = mediacontrol_ModuloPosition;   break;
+    } 
+
+    return origin_position;
+}
+
+/* Methods for transforming the Position Python object to Position structure*/ 
+static mediacontrol_Position* position_py_to_c( PyObject * py_position )
+{
+    mediacontrol_Position * a_position = NULL;
+    PyPosition *pos = (PyPosition*)py_position;
+
+    a_position = (mediacontrol_Position*)malloc(sizeof(mediacontrol_Position));
+    if (! a_position)
+      {
+       PyErr_SetString(PyExc_MemoryError, "Out of memory");
+       return NULL;
+      }
+
+    if (PyObject_IsInstance(py_position, (PyObject*)&PyPosition_Type))
+      {
+       a_position->origin = pos->origin;
+       a_position->key    = pos->key;
+       a_position->value  = pos->value;
+      }
+    else
+      {
+       /* Feature: if we give an integer, it will be considered as 
+          a relative position in mediatime */
+       a_position->origin = mediacontrol_RelativePosition;
+       a_position->key    = mediacontrol_MediaTime;
+       a_position->value  = PyLong_AsLongLong(py_position);
+      }   
+    return a_position;
+}
+
+static PyPosition* position_c_to_py(mediacontrol_Position *position)
+{
+  PyPosition* py_retval;
+
+  py_retval = PyObject_New(PyPosition, &PyPosition_Type);
+  py_retval->origin = position->origin;
+  py_retval->key    = position->key;
+  py_retval->value  = position->value;
+
+  return py_retval;
+}
+
+/* constructor : create the new type, thread and init */
+static PyObject *MediaControl_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+  MediaControl *self;
+  mediacontrol_Exception *exception = NULL;
+  PyObject* py_list = NULL;
+  char** ppsz_args = NULL;
+
+  self = PyObject_New(MediaControl, &MediaControl_Type);
+
+  if (PyArg_ParseTuple(args, "O", &py_list))
+    {
+      int i_size;
+      int i_index;
+
+      Py_INCREF(py_list);
+      if (! PySequence_Check(py_list))
+       {
+         PyErr_SetString(PyExc_TypeError, "Parameter must be a sequence.");
+         return NULL;
+       }
+      i_size = PySequence_Size(py_list);
+      ppsz_args = malloc(i_size + 1);
+      if (! ppsz_args)
+      {
+       PyErr_SetString(PyExc_MemoryError, "Out of memory");
+       return NULL;
+      }
+
+      for (i_index = 0; i_index < i_size; i_index++)
+       {
+         ppsz_args[i_index]=strdup(PyString_AsString(PyObject_Str(PySequence_GetItem(py_list, 
+                                                                                     i_index))));
+       }
+      ppsz_args[i_size] = NULL;
+      Py_DECREF(py_list);
+    }
+  
+  Py_BEGIN_ALLOW_THREADS
+  MC_TRY;
+  self->mc = mediacontrol_new(ppsz_args, exception);
+  MC_EXCEPT;
+  Py_END_ALLOW_THREADS
+  
+  Py_INCREF(self);
+  return (PyObject *)self;
+}
+
+static void
+MediaControl_dealloc(PyObject *self)
+{
+  PyMem_DEL(self);
+}
+
+/* Returns the current position in the stream. The returned value can
+   be relative or absolute (according to PositionOrigin) and the unit
+   is set by PositionKey */
+static PyObject * MediaControl_get_media_position(PyObject *self, PyObject *args)
+{
+  mediacontrol_Position* pos;
+  mediacontrol_Exception* exception = NULL;
+  PyObject *py_origin;
+  PyObject *py_key;
+  PyObject *py_retval;
+  mediacontrol_PositionOrigin origin;
+  mediacontrol_PositionKey key;
+  
+  if( !PyArg_ParseTuple(args, "OO", &py_origin, &py_key))
+      return NULL;
+  origin = positionOrigin_py_to_c(py_origin);
+  key    = positionKey_py_to_c(py_key);
+
+  Py_BEGIN_ALLOW_THREADS
+  MC_TRY;
+  pos = mediacontrol_get_media_position(SELF->mc, origin, key, exception);
+  Py_END_ALLOW_THREADS
+  MC_EXCEPT;
+
+  py_retval = (PyObject*)position_c_to_py(pos);
+  free(pos);
+  return py_retval;
+}
+
+/* Sets the media position */
+static PyObject *MediaControl_set_media_position(PyObject *self, PyObject *args)
+{
+  mediacontrol_Exception* exception = NULL;
+  mediacontrol_Position *a_position;
+  PyObject *py_pos;
+
+  if( !PyArg_ParseTuple(args, "O", &py_pos) )
+    return NULL;
+
+  a_position = position_py_to_c(py_pos);
+  if (!a_position)
+    {
+      PyErr_SetString(PyExc_MemoryError, "Out of memory");
+      return NULL;
+    }
+
+  Py_BEGIN_ALLOW_THREADS
+  MC_TRY;
+  mediacontrol_set_media_position(SELF->mc, a_position, exception);
+  free(a_position);
+  Py_END_ALLOW_THREADS
+  MC_EXCEPT;
+
+  Py_INCREF(Py_None);
+  return Py_None;
+}
+
+static PyObject *MediaControl_start(PyObject *self, PyObject *args)
+{
+  mediacontrol_Position *a_position;
+  mediacontrol_Exception *exception = NULL;
+  PyObject *py_pos;
+  
+  if( !PyArg_ParseTuple(args, "O", &py_pos))
+    return NULL;
+    
+  a_position = position_py_to_c(py_pos);
+  if (!a_position)
+      return NULL;
+  
+  Py_BEGIN_ALLOW_THREADS
+  MC_TRY;
+  mediacontrol_start(SELF->mc, a_position, exception);
+  free(a_position);
+  Py_END_ALLOW_THREADS
+  MC_EXCEPT;
+  
+  Py_INCREF(Py_None);
+  return Py_None; 
+}
+
+static PyObject *MediaControl_pause(PyObject *self, PyObject *args)
+{
+  mediacontrol_Position *a_position;
+  mediacontrol_Exception *exception = NULL;
+  PyObject *py_pos;
+  
+  if( !PyArg_ParseTuple(args, "O", &py_pos))
+    return NULL;
+  
+  a_position = position_py_to_c(py_pos);
+  
+  Py_BEGIN_ALLOW_THREADS
+  MC_TRY;
+  mediacontrol_pause(SELF->mc, a_position, exception);
+  free(a_position);
+  Py_END_ALLOW_THREADS
+  MC_EXCEPT;
+    
+  Py_INCREF(Py_None);
+  return Py_None; 
+}
+
+static PyObject * MediaControl_resume(PyObject *self, PyObject *args)
+{
+  mediacontrol_Position *a_position;
+  mediacontrol_Exception *exception = NULL;
+  PyObject *py_pos;
+  
+  if( !PyArg_ParseTuple(args, "O", &py_pos))
+    return NULL;
+  
+  a_position = position_py_to_c(py_pos);
+  
+  Py_BEGIN_ALLOW_THREADS
+  MC_TRY;
+  mediacontrol_start(SELF->mc, a_position, exception);
+  free(a_position);
+  Py_END_ALLOW_THREADS
+  MC_EXCEPT;
+  
+  Py_INCREF(Py_None);
+  return Py_None; 
+}
+
+static PyObject *MediaControl_stop(PyObject *self, PyObject *args)
+{
+  mediacontrol_Position *a_position;
+  mediacontrol_Exception *exception = NULL;
+  PyObject *py_pos;
+  
+  if( !PyArg_ParseTuple(args, "O", &py_pos))
+    return NULL;
+    
+  a_position = position_py_to_c(py_pos);
+  
+  Py_BEGIN_ALLOW_THREADS
+  MC_TRY;
+  mediacontrol_stop(SELF->mc, a_position, exception);
+  free(a_position);
+  Py_END_ALLOW_THREADS
+  MC_EXCEPT;
+  
+  Py_INCREF(Py_None);
+  return Py_None; 
+}
+
+static PyObject *MediaControl_exit(PyObject *self, PyObject *args)
+{
+  mediacontrol_exit(SELF->mc);
+  Py_INCREF(Py_None);
+  return Py_None;
+}
+
+static PyObject *MediaControl_playlist_add_item(PyObject *self, PyObject *args)
+{
+  char *psz_file;
+  mediacontrol_Exception *exception = NULL;
+  
+  if ( !PyArg_ParseTuple(args, "s", &psz_file) )
+    return NULL;
+  
+  Py_BEGIN_ALLOW_THREADS
+  MC_TRY;
+  mediacontrol_playlist_add_item(SELF->mc, psz_file, exception);
+  Py_END_ALLOW_THREADS
+  MC_EXCEPT;
+    
+  Py_INCREF(Py_None);
+  return Py_None;    
+}
+
+static PyObject * MediaControl_playlist_clear(PyObject *self,
+                                             PyObject *args)
+{
+  mediacontrol_Exception *exception = NULL;
+  
+  Py_BEGIN_ALLOW_THREADS
+  MC_TRY;
+  mediacontrol_playlist_clear(SELF->mc, exception);
+  Py_END_ALLOW_THREADS
+  MC_EXCEPT;
+  
+  Py_INCREF(Py_None);
+  return Py_None;      
+}
+
+static PyObject * MediaControl_playlist_get_list(PyObject *self,
+                                                PyObject *args)
+{
+  PyObject *py_retval;
+  mediacontrol_Exception *exception = NULL;
+  mediacontrol_PlaylistSeq* pl;
+  int i_index;
+  int i_playlist_size;
+  
+  Py_BEGIN_ALLOW_THREADS
+  MC_TRY;
+  pl = mediacontrol_playlist_get_list(SELF->mc, exception);
+  Py_END_ALLOW_THREADS
+  MC_EXCEPT;
+
+  i_playlist_size = pl->size;
+  
+  py_retval = PyTuple_New(i_playlist_size);
+
+  for (i_index = 0 ; i_index < i_playlist_size ; i_index++)
+    {
+      PyTuple_SetItem(py_retval, i_index, Py_BuildValue("s", pl->data[i_index]));
+    }
+  mediacontrol_PlaylistSeq__free(pl);
+
+  return py_retval;
+}
+
+
+static PyObject * MediaControl_snapshot(PyObject *self, PyObject *args)
+{
+  mediacontrol_RGBPicture *retval  = NULL;
+  mediacontrol_Exception* exception = NULL;
+  mediacontrol_Position *a_position    = NULL;
+  PyObject *py_pos        = NULL;
+  PyObject *py_obj        = NULL;
+  
+  if( !PyArg_ParseTuple(args, "O", &py_pos))
+    return NULL;
+  
+  a_position = position_py_to_c(py_pos);
+  
+  Py_BEGIN_ALLOW_THREADS
+  MC_TRY;
+  retval = mediacontrol_snapshot(SELF->mc, a_position, exception);
+  free(a_position);
+  Py_END_ALLOW_THREADS
+  MC_EXCEPT;
+
+  if( !retval ) {
+      Py_INCREF( Py_None );  
+      return Py_None;
+  }
+    
+  /* FIXME: create a real RGBPicture object */
+  py_obj = PyDict_New();
+  
+  PyDict_SetItemString(py_obj, "width",   Py_BuildValue("i", retval->width));
+  PyDict_SetItemString(py_obj, "height",      Py_BuildValue("i", retval->height));
+  PyDict_SetItemString(py_obj, "type", Py_BuildValue("i", retval->type));
+  PyDict_SetItemString(py_obj, "data",     Py_BuildValue("s#", retval->data, retval->size));
+  
+  /*  Py_INCREF(py_obj); */
+  return py_obj;
+}
+
+static PyObject* MediaControl_display_text(PyObject *self, PyObject *args)
+{  
+  mediacontrol_Exception* exception = NULL;
+  PyObject *py_begin, *py_end;
+  char* message;
+  mediacontrol_Position * begin;
+  mediacontrol_Position * end;
+
+  if( !PyArg_ParseTuple(args, "sOO", &message, &py_begin, &py_end))
+    return NULL;
+  
+  begin = position_py_to_c(py_begin);
+  end   = position_py_to_c(py_end);
+  
+  Py_BEGIN_ALLOW_THREADS
+  MC_TRY;
+  mediacontrol_display_text(SELF->mc, message, begin, end, exception);
+  Py_END_ALLOW_THREADS
+  MC_EXCEPT;
+
+  free(begin);
+  free(end);
+  
+  Py_INCREF(Py_None);  
+  return Py_None;
+}
+
+static PyObject* MediaControl_get_stream_information(PyObject *self, PyObject *args)
+{
+  mediacontrol_StreamInformation *retval  = NULL;
+  mediacontrol_Exception* exception = NULL;
+  PyObject *py_obj;
+
+  Py_BEGIN_ALLOW_THREADS
+  MC_TRY;
+  retval = mediacontrol_get_stream_information(SELF->mc, mediacontrol_MediaTime, exception);
+  Py_END_ALLOW_THREADS
+  MC_EXCEPT;
+   
+  py_obj = PyDict_New();
+
+   /* FIXME: create a real StreamInformation object */
+  PyDict_SetItemString(py_obj, "status",   Py_BuildValue("i", retval->streamstatus));
+  PyDict_SetItemString(py_obj, "url",      Py_BuildValue("s", retval->url));
+  PyDict_SetItemString(py_obj, "position", Py_BuildValue("L", retval->position));
+  PyDict_SetItemString(py_obj, "length",   Py_BuildValue("L", retval->length));
+  
+  free(retval->url);
+  free(retval);
+
+  /* Py_INCREF(py_obj); */
+  return py_obj;
+}
+
+static PyObject* MediaControl_sound_set_volume(PyObject *self, PyObject *args)
+{
+  mediacontrol_Exception* exception = NULL;
+  unsigned short volume;
+  
+  if (!PyArg_ParseTuple(args, "H", &volume))
+     return NULL;
+
+  Py_BEGIN_ALLOW_THREADS
+  MC_TRY;
+  mediacontrol_sound_set_volume(SELF->mc, volume, exception);
+  Py_END_ALLOW_THREADS
+  MC_EXCEPT;
+   
+  Py_INCREF(Py_None);
+  return Py_None;
+}
+
+static PyObject* MediaControl_sound_get_volume(PyObject *self, PyObject *args)
+{
+  mediacontrol_Exception* exception = NULL;
+  PyObject *py_retval;
+  unsigned short volume;
+  
+  Py_BEGIN_ALLOW_THREADS
+  MC_TRY;
+  volume=mediacontrol_sound_get_volume(SELF->mc, exception);
+  Py_END_ALLOW_THREADS
+  MC_EXCEPT;
+  
+  py_retval = Py_BuildValue("H", volume);
+  return py_retval;
+}
+
+/* Method table */
+static PyMethodDef MediaControl_methods[] = {
+  {"get_media_position", MediaControl_get_media_position, METH_VARARGS, "get_media_position(origin, key) -> Position    Get current media position."},
+  {"set_media_position", MediaControl_set_media_position, METH_VARARGS, "set_media_position(Position)            Set media position"},
+  {"start", MediaControl_start, METH_VARARGS, "start(Position)         Start the player."},
+  {"pause", MediaControl_pause, METH_VARARGS, "pause(Position)         Pause the player."},
+  {"resume", MediaControl_resume, METH_VARARGS, "resume(Position)        Resume the player"},
+  {"stop", MediaControl_stop, METH_VARARGS, "stop(Position)              Stop the player"},
+  {"exit", MediaControl_exit, METH_VARARGS, "exit()                     Exit the player"},
+  {"playlist_add_item", MediaControl_playlist_add_item, METH_VARARGS, "playlist_add_item(str)               Add an item to the playlist"},
+  {"playlist_get_list", MediaControl_playlist_get_list, METH_VARARGS, "playlist_get_list() -> list       Get the contents of the playlist"},
+  {"playlist_clear", MediaControl_playlist_clear, METH_VARARGS, "clear()         Clear the playlist."},
+  {"snapshot", MediaControl_snapshot, METH_VARARGS, "snapshot(Position) -> dict        Take a snapshot"},
+  {"display_text", MediaControl_display_text, METH_VARARGS, "display_text(str, Position, Position)    Display a text on the video"},
+  {"get_stream_information", MediaControl_get_stream_information, METH_VARARGS, "get_stream_information() -> dict      Get information about the stream"},
+  {"sound_get_volume", MediaControl_sound_get_volume, METH_VARARGS, "sound_get_volume() -> int       Get the volume"},
+  {"sound_set_volume", MediaControl_sound_set_volume, METH_VARARGS, "sound_set_volume(int)           Set the volume"},
+  {NULL, NULL, 0, NULL},
+};
+
+static PyTypeObject MediaControl_Type = {
+    PyObject_HEAD_INIT(NULL)
+    0,                         /*ob_size*/
+    "vlc.MediaControl",        /*tp_name*/
+    sizeof(MediaControl_Type), /*tp_basicsize*/
+    0,                         /*tp_itemsize*/
+    (destructor)MediaControl_dealloc,      /*tp_dealloc*/
+    0,                         /*tp_print*/
+    0,                         /*tp_getattr*/
+    0,                         /*tp_setattr*/
+    0,                         /*tp_compare*/
+    0,                         /*tp_repr*/
+    0,                         /*tp_as_number*/
+    0,                         /*tp_as_sequence*/
+    0,                         /*tp_as_mapping*/
+    0,                         /*tp_hash */
+    0,                         /*tp_call*/
+    0,                         /*tp_str*/
+    0,                         /*tp_getattro*/
+    0,                         /*tp_setattro*/
+    0,                         /*tp_as_buffer*/
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
+    "Control of a VLC instance.",  /* tp_doc */
+    0,                        /* tp_traverse */
+    0,                        /* tp_clear */
+    0,                        /* tp_richcompare */
+    0,                        /* tp_weaklistoffset */
+    0,                        /* tp_iter */
+    0,                        /* tp_iternext */
+    MediaControl_methods,             /* tp_methods */
+    0,             /* tp_members */
+    0,                         /* tp_getset */
+    0,                         /* tp_base */
+    0,                         /* tp_dict */
+    0,                         /* tp_descr_get */
+    0,                         /* tp_descr_set */
+    0,                         /* tp_dictoffset */
+    0,                         /* tp_init */
+    0,                         /* tp_alloc */
+    MediaControl_new,          /* tp_new */
+};
+
+#ifdef VLCOBJECT_SUPPORT
+
+/***** vlcObject definitions *****/
+/* constructor : create the new type, thread and init */
+static PyObject *vlcObject_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+  vlcObject *self;
+  vlc_object_t *p_object;
+  int i_id;
+  
+  self = PyObject_New(vlcObject, &vlcObject_Type);
+
+  if ( !PyArg_ParseTuple(args, "i", &i_id) )
+    return NULL;
+
+  /* Maybe we were already initialized */
+  p_object = (vlc_object_t*)vlc_current_object(i_id);
+
+  if (! p_object)
+    {
+      /* Try to initialize */
+      i_id = VLC_Create();
+      p_object = (vlc_object_t*)vlc_current_object(i_id);
+    }
+  
+  if (! p_object)
+    {
+      PyErr_SetString(PyExc_StandardError, "Unable to get object.");
+      return NULL;
+    }
+
+  self->p_object = p_object;
+  Py_INCREF(self); /* Ah bon ? */
+  return (PyObject *)self;
+}
+
+static void
+vlcObject_dealloc(PyObject *self)
+{
+  vlc_object_release(VLCSELF->p_object);
+  PyMem_DEL(self);
+}
+
+static PyObject * vlcObject_find_object(PyObject *self,
+                                        PyObject *args)
+{
+  vlcObject *retval;
+  vlc_object_t *p_obj;
+  char *psz_name;
+  int i_object_type;
+
+  if ( !PyArg_ParseTuple(args, "s", &psz_name) )
+    return NULL;
+
+  /* psz_name is in
+     (aout, decoder, input, httpd, intf, playlist, root, vlc, vout)
+  */
+  switch (psz_name[0])
+    {
+    case 'a':
+      i_object_type = VLC_OBJECT_AOUT;
+      break;
+    case 'd':
+      i_object_type = VLC_OBJECT_DECODER;
+      break;
+    case 'h':
+      i_object_type = VLC_OBJECT_HTTPD;
+      break;
+    case 'i':
+      if (strlen(psz_name) < 3)
+       i_object_type = VLC_OBJECT_INTF;
+      else if (psz_name[2] == 't')
+       i_object_type = VLC_OBJECT_INTF;
+      else
+       i_object_type = VLC_OBJECT_INPUT;
+      break;
+    case 'p':
+      i_object_type = VLC_OBJECT_PLAYLIST;
+      break;
+    case 'r':
+      i_object_type = VLC_OBJECT_ROOT;
+      break;
+    case 'v':
+      if (strlen(psz_name) < 3)        
+       i_object_type = VLC_OBJECT_VLC;
+      else if (psz_name[1] == 'l')
+       i_object_type = VLC_OBJECT_VLC;
+      else
+       i_object_type = VLC_OBJECT_VOUT;
+      break;
+    default:
+      /* FIXME: raise an exception */
+      return Py_None;
+    }
+
+  p_obj = vlc_object_find( VLCSELF->p_object, i_object_type, FIND_ANYWHERE );
+  
+  if (! p_obj)
+    {
+      Py_INCREF(Py_None);
+      return Py_None;
+    }
+
+  retval = PyObject_New(vlcObject, &vlcObject_Type);
+  
+  retval->p_object = p_obj;
+  return (PyObject *)retval;
+}
+
+static PyObject * vlcObject_info(PyObject *self,
+                                   PyObject *args)
+{
+  PyObject *retval;
+  vlc_object_t *p_obj;
+
+  p_obj = VLCSELF->p_object;
+  
+  /* Return information about the object as a dict. */
+  retval = PyDict_New();
+  
+  PyDict_SetItemString(retval, "object-id", Py_BuildValue("l", p_obj->i_object_id));
+  PyDict_SetItemString(retval, "object-type", Py_BuildValue("s", p_obj->psz_object_type));
+  PyDict_SetItemString(retval, "object-name", Py_BuildValue("s", p_obj->psz_object_name));
+  PyDict_SetItemString(retval, "thread", PyBool_FromLong(p_obj->b_thread));
+  PyDict_SetItemString(retval, "thread-id", PyLong_FromLongLong(p_obj->thread_id));
+  PyDict_SetItemString(retval, "refcount", PyInt_FromLong(p_obj->i_refcount));
+
+  return retval;
+}
+
+static PyObject * vlcObject_find_id(PyObject *self,
+                                    PyObject *args)
+{
+  vlcObject *retval;
+  vlc_object_t* p_object;
+  int i_id;
+
+  if ( !PyArg_ParseTuple(args, "i", &i_id) )
+    {
+      PyErr_SetString(PyExc_StandardError, "Error: no id was given.\n");
+      return Py_None;
+    }
+
+  p_object = (vlc_object_t*)vlc_current_object(i_id);
+
+  if (! p_object)
+    {
+      Py_INCREF(Py_None);
+      return Py_None;
+    }
+
+  retval = PyObject_NEW(vlcObject, &vlcObject_Type);
+  
+  retval->p_object = p_object;
+  return (PyObject *)retval;
+}
+
+/* Do a var_Get call on the object. Parameter: the variable name. */
+/* FIXME: We should make them attributes */
+static PyObject * vlcObject_var_get(PyObject *self,
+                                      PyObject *args)
+{
+  PyObject *retval;
+  vlc_value_t value;
+  char *psz_name;
+  int i_type;
+  
+  if ( !PyArg_ParseTuple(args, "s", &psz_name) )
+    {
+      PyErr_SetString(PyExc_StandardError, "Error: no variable name was given.\n");
+      Py_INCREF(Py_None);
+      return Py_None;
+    }
+
+  if( var_Get( VLCSELF->p_object, psz_name, &value ) != VLC_SUCCESS )
+    {
+      PyErr_SetString(PyExc_StandardError, "Error: no variable name was given.\n");
+      Py_INCREF(Py_None);
+      return Py_None;
+    }
+  
+  i_type = var_Type (VLCSELF->p_object, psz_name);
+
+  switch (i_type)
+    {
+    case VLC_VAR_VOID   :
+      retval = PyString_FromString("A void variable");
+      break;
+    case VLC_VAR_BOOL      :
+      retval = PyBool_FromLong(value.b_bool);
+      break;
+    case VLC_VAR_INTEGER   :
+      retval = PyInt_FromLong((long)value.i_int);
+      break;
+    case VLC_VAR_HOTKEY   :
+      retval = PyString_FromFormat("A hotkey variable (%d)", value.i_int);
+      break;
+    case VLC_VAR_FILE      :
+    case VLC_VAR_STRING    :
+    case VLC_VAR_DIRECTORY :
+    case VLC_VAR_VARIABLE  :
+      retval = PyString_FromString(value.psz_string);
+      break;
+    case VLC_VAR_MODULE   :
+      retval = (PyObject*)PyObject_New(vlcObject, &vlcObject_Type);
+      ((vlcObject*)retval)->p_object = value.p_object;
+      break;
+    case VLC_VAR_FLOAT     :
+      retval = PyFloat_FromDouble((double)value.f_float);
+      break;
+    case VLC_VAR_TIME      :
+      retval = PyLong_FromLongLong(value.i_time);
+      break;
+    case VLC_VAR_ADDRESS   :
+      retval = PyString_FromString("A VLC address (not handled yet)");
+      break;
+    case VLC_VAR_LIST      :
+      retval = PyString_FromString("A VLC list (not handled yet)");
+      break;
+    case VLC_VAR_MUTEX :
+      retval = PyString_FromString("A mutex");
+      break;
+    default:
+      retval = Py_None;
+    }
+
+  Py_INCREF(retval);
+  return retval;
+}
+
+static PyObject * vlcObject_var_type(PyObject *self,
+                                    PyObject *args)
+{
+  char *psz_name;
+  PyObject *retval;
+  int i_type;
+
+  if ( !PyArg_ParseTuple(args, "s", &psz_name))
+    {
+      PyErr_SetString(PyExc_StandardError, "Error: no variable name was given.\n");
+      Py_INCREF(Py_None);
+      return Py_None;
+    }
+
+  i_type = var_Type(VLCSELF->p_object, psz_name);
+  
+  switch (i_type)
+    {
+    case VLC_VAR_VOID   :
+      retval = PyString_FromString("Void");
+      break;
+    case VLC_VAR_BOOL      :
+      retval = PyString_FromString("Boolean");
+      break;
+    case VLC_VAR_INTEGER   :
+      retval = PyString_FromString("Integer");
+      break;
+    case VLC_VAR_HOTKEY   :
+      retval = PyString_FromString("Hotkey");
+      break;
+    case VLC_VAR_FILE      :
+      retval = PyString_FromString("File");
+      break;
+    case VLC_VAR_STRING    :
+      retval = PyString_FromString("String");
+      break;
+    case VLC_VAR_DIRECTORY :
+      retval = PyString_FromString("Directory");
+      break;
+    case VLC_VAR_VARIABLE  :
+      retval = PyString_FromString("Variable");
+      break;
+    case VLC_VAR_MODULE   :
+      retval = PyString_FromString("Module");
+      break;
+    case VLC_VAR_FLOAT     :
+      retval = PyString_FromString("Float");
+      break;
+    case VLC_VAR_TIME      :
+      retval = PyString_FromString("Time");
+      break;
+    case VLC_VAR_ADDRESS   :
+      retval = PyString_FromString("Address");
+      break;
+    case VLC_VAR_LIST      :
+      retval = PyString_FromString("List");
+      break;
+    case VLC_VAR_MUTEX :
+      retval = PyString_FromString("Mutex");
+      break;
+    default:
+      retval = PyString_FromString("Unknown");
+    }
+  return retval;
+}
+
+/* Do a var_Set call on the object. Parameter: the variable name. */
+/* FIXME: We should make them attributes */
+static PyObject * vlcObject_var_set(PyObject *self,
+                                    PyObject *args)
+{
+  vlc_value_t value;
+  char *psz_name;
+  PyObject *py_value;
+  int i_type;
+  vlc_object_t *p_obj;
+  
+  if ( !PyArg_ParseTuple(args, "sO", &psz_name, &py_value) )
+    {
+      PyErr_SetString(PyExc_StandardError, "Error: no variable name was given.\n");
+      Py_INCREF(Py_None);
+      return Py_None;
+    }
+
+  p_obj = VLCSELF->p_object;
+  i_type = var_Type(p_obj, psz_name);
+  
+  switch (i_type)
+    {
+    case VLC_VAR_VOID   :
+      break;
+    case VLC_VAR_BOOL      :
+      value.b_bool = PyInt_AsLong(py_value);
+      break;
+    case VLC_VAR_INTEGER   :
+    case VLC_VAR_HOTKEY   :
+      value.i_int = PyInt_AsLong(py_value);
+      break;
+    case VLC_VAR_FILE      :
+    case VLC_VAR_STRING    :
+    case VLC_VAR_DIRECTORY :
+    case VLC_VAR_VARIABLE  :
+      value.psz_string = strdup(PyString_AsString(py_value));
+      break;
+    case VLC_VAR_MODULE   :
+      /* FIXME: we should check the PyObject type and get its p_object */
+      value.p_object = ((vlcObject*)p_obj)->p_object;
+      break;
+    case VLC_VAR_FLOAT     :
+      value.f_float = PyFloat_AsDouble(py_value);
+      break;
+    case VLC_VAR_TIME      :
+      value.i_time = PyLong_AsLongLong(py_value);
+      break;
+    case VLC_VAR_ADDRESS   :
+      value.p_address = (char*)PyLong_AsVoidPtr(py_value);
+      break;
+    case VLC_VAR_LIST      :
+      /* FIXME */
+      value.p_list = NULL;
+      break;
+    case VLC_VAR_MUTEX :
+      break;
+    }
+
+  var_Set(p_obj, psz_name, value);
+
+  Py_INCREF(Py_None);
+  return Py_None;
+}
+
+static PyObject * vlcObject_var_list(PyObject *self,
+                                    PyObject *args)
+{
+  PyObject *retval;
+  int i_size;
+  int i_index;
+  
+  i_size = VLCSELF->p_object->i_vars;
+  retval = PyTuple_New(i_size);
+
+  for (i_index = 0 ; i_index < i_size ; i_index++)
+    {
+      PyTuple_SetItem(retval, i_index, 
+                     Py_BuildValue("s", VLCSELF->p_object->p_vars[i_index].psz_name));
+   }
+  
+  /* Py_INCREF(retval); */
+  return retval;
+}
+
+/* Do a config_Get call on the object. Parameter: the variable name. */
+static PyObject * vlcObject_config_get(PyObject *self,
+                                      PyObject *args)
+{
+  PyObject *retval;
+  vlc_value_t value;
+  char *psz_name;
+  module_config_t *p_config;
+  
+  if ( !PyArg_ParseTuple(args, "s", &psz_name) )
+    {
+      PyErr_SetString(PyExc_StandardError, "Error: no config variable name was given.\n");
+      Py_INCREF(Py_None);
+      return Py_None;
+    }
+
+  p_config = config_FindConfig( VLCSELF->p_object, psz_name );
+
+  if( !p_config )
+    {
+      PyErr_SetString(PyExc_StandardError, "Error: config variable does not exist.\n");
+      Py_INCREF(Py_None);
+      return Py_None;
+    }
+  
+  switch (p_config->i_type)
+    {
+    case CONFIG_ITEM_BOOL      :
+      retval = PyBool_FromLong(p_config->i_value);
+      break;
+    case CONFIG_ITEM_INTEGER   :
+      retval = PyInt_FromLong((long)p_config->i_value);
+      break;
+    case CONFIG_ITEM_KEY   :
+      retval = PyString_FromFormat("A hotkey variable (%d)", p_config->i_value);
+      break;
+    case CONFIG_ITEM_FILE      :
+    case CONFIG_ITEM_STRING    :
+    case CONFIG_ITEM_DIRECTORY :
+    case CONFIG_ITEM_MODULE    :
+      vlc_mutex_lock( p_config->p_lock );
+      if( p_config->psz_value ) 
+       retval = PyString_FromString( p_config->psz_value );
+      else
+       retval = PyString_FromString( "" );
+      vlc_mutex_unlock( p_config->p_lock );
+      break;
+      retval = (PyObject*)PyObject_New(vlcObject, &vlcObject_Type);
+      ((vlcObject*)retval)->p_object = value.p_object;
+      break;
+    case CONFIG_ITEM_FLOAT     :
+      retval = PyFloat_FromDouble((double)p_config->f_value);
+      break;
+    default:
+      retval = Py_None;
+      Py_INCREF(retval);
+    }
+
+  return retval;
+}
+
+/* Do a var_Set call on the object. Parameter: the variable name. */
+/* FIXME: We should make them attributes */
+static PyObject * vlcObject_config_set(PyObject *self,
+                                      PyObject *args)
+{
+  char *psz_name;
+  PyObject *py_value;
+  vlc_object_t *p_obj;
+  module_config_t *p_config;
+
+  
+  if ( !PyArg_ParseTuple(args, "sO", &psz_name, &py_value) )
+    {
+      PyErr_SetString(PyExc_StandardError, "Error: no variable name was given.\n");
+      Py_INCREF(Py_None);
+      return Py_None;
+    }
+
+  p_obj = VLCSELF->p_object;
+  p_config = config_FindConfig( p_obj, psz_name );
+  /* sanity checks */
+  if( !p_config )
+    {
+      PyErr_SetString(PyExc_StandardError, "Error: option does not exist.\n");
+      Py_INCREF(Py_None);
+      return Py_None;
+    }
+  
+  switch (p_config->i_type)
+    {
+    case CONFIG_ITEM_BOOL      :
+    case CONFIG_ITEM_INTEGER   :
+    case CONFIG_ITEM_KEY       :
+      config_PutInt(p_obj, psz_name, PyInt_AsLong(py_value));
+      break;
+    case CONFIG_ITEM_FILE      :
+    case CONFIG_ITEM_STRING    :
+    case CONFIG_ITEM_DIRECTORY :
+    case CONFIG_ITEM_MODULE   :
+      config_PutPsz(p_obj, psz_name, PyString_AsString(py_value));
+      break;
+    case CONFIG_ITEM_FLOAT     :
+      config_PutFloat(p_obj, psz_name, PyFloat_AsDouble(py_value));
+      break;
+    }
+  Py_INCREF(Py_None);
+  return Py_None;
+}
+
+static PyObject * vlcObject_children(PyObject *self,
+                                    PyObject *args)
+{
+  PyObject *retval;
+  int i_size;
+  int i_index;
+  
+  i_size = VLCSELF->p_object->i_children;
+  retval = PyTuple_New(i_size);
+
+  for (i_index = 0 ; i_index < i_size ; i_index++)
+    {
+      PyTuple_SetItem(retval, i_index, 
+                     Py_BuildValue("i", VLCSELF->p_object->pp_children[i_index]->i_object_id));
+    }
+  
+  /* Py_INCREF(retval); */
+  return retval;
+}
+
+/* Method table */
+static PyMethodDef vlcObject_methods[] = {
+  {"get", vlcObject_var_get, METH_VARARGS, "get(str) -> value   Get a variable value."},
+  {"set", vlcObject_var_set, METH_VARARGS, "set(str, value)     Set a variable value"},
+  {"config_get", vlcObject_config_get, METH_VARARGS, "get(str) -> value   Get an option value."},
+  {"config_set", vlcObject_config_set, METH_VARARGS, "set(str, value)     Set an option value"},
+  {"type", vlcObject_var_type, METH_VARARGS, "type(str) -> str     Get a variable type"},
+  {"list", vlcObject_var_list, METH_VARARGS, "list()             List the available variables"},
+  {"children", vlcObject_children, METH_VARARGS, "children()             List the children ids"},
+  {"find_object", vlcObject_find_object, METH_VARARGS, "find_object(str) -> Object     Find the object of a given type.\n\nAvailable types are : aout, decoder, input, httpd, intf, playlist, root, vlc, vout"},
+  {"find_id", vlcObject_find_id, METH_VARARGS, "find_id(int) -> Object      Find an object by id"},
+  {"info", vlcObject_info, METH_VARARGS, "info() -> dict    Return information about the object"},
+  {NULL, NULL, 0, NULL},
+};
+
+static PyTypeObject vlcObject_Type = {
+    PyObject_HEAD_INIT(NULL)
+    0,                         /*ob_size*/
+    "vlc.Object",       /*tp_name*/
+    sizeof(vlcObject_Type), /*tp_basicsize*/
+    0,                         /*tp_itemsize*/
+    (destructor)vlcObject_dealloc,      /*tp_dealloc*/
+    0,                         /*tp_print*/
+    0,                         /*tp_getattr*/
+    0,                         /*tp_setattr*/
+    0,                         /*tp_compare*/
+    0,                         /*tp_repr*/
+    0,                         /*tp_as_number*/
+    0,                         /*tp_as_sequence*/
+    0,                         /*tp_as_mapping*/
+    0,                         /*tp_hash */
+    0,                         /*tp_call*/
+    0,                         /*tp_str*/
+    0,                         /*tp_getattro*/
+    0,                         /*tp_setattro*/
+    0,                         /*tp_as_buffer*/
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
+    "Explore VLC objects.",  /* tp_doc */
+    0,                        /* tp_traverse */
+    0,                        /* tp_clear */
+    0,                        /* tp_richcompare */
+    0,                        /* tp_weaklistoffset */
+    0,                        /* tp_iter */
+    0,                        /* tp_iternext */
+    vlcObject_methods,             /* tp_methods */
+    0,             /* tp_members */
+    0,                         /* tp_getset */
+    0,                         /* tp_base */
+    0,                         /* tp_dict */
+    0,                         /* tp_descr_get */
+    0,                         /* tp_descr_set */
+    0,                         /* tp_dictoffset */
+    0,                         /* tp_init */
+    0,                         /* tp_alloc */
+    vlcObject_new,          /* tp_new */
+};
+
+/***** End of vlcObject definitions *****/
+#endif 
+
+/* Module functions */
+
+static PyMethodDef vlc_methods[] = {
+    {NULL}  /* Sentinel */
+};
+
+
+#ifndef vlcMODINIT_FUNC        /* declarations for DLL import/export */
+#define vlcMODINIT_FUNC void
+#endif
+vlcMODINIT_FUNC
+initvlc(void) 
+{
+  PyObject* m;
+
+  PyPosition_Type.tp_new = PyType_GenericNew;
+  PyPosition_Type.tp_alloc = PyType_GenericAlloc;
+
+  if (PyType_Ready(&PyPosition_Type) < 0)
+      return;
+  if (PyType_Ready(&MediaControl_Type) < 0)
+      return;
+#ifdef VLCOBJECT_SUPPORT
+  if (PyType_Ready(&vlcObject_Type) < 0)
+      return;
+#endif
+
+  /*  PyEval_InitThreads(); */
+
+  /* Have a look at
+     http://base.bel-epa.com/pyapache/Python/MySQL-python/MySQL-python-0.3.0/_mysqlmodule.c */
+
+  m = Py_InitModule3("vlc", vlc_methods, "VideoLan Client embedding module.");
+
+  /* Exceptions */
+  MediaControl_InternalException = PyErr_NewException("vlc.InternalException", NULL, NULL);
+  PyModule_AddObject(m, "InternalException", MediaControl_InternalException);
+
+  MediaControl_PositionKeyNotSupported = PyErr_NewException("vlc.PositionKeyNotSupported", 
+                                                           NULL, NULL);
+  PyModule_AddObject(m, "PositionKeyNotSupported", MediaControl_PositionKeyNotSupported);
+
+  MediaControl_PositionOriginNotSupported=PyErr_NewException("vlc.InvalidPosition", NULL, NULL);
+  PyModule_AddObject(m, "PositionOriginNotSupported", MediaControl_PositionOriginNotSupported);
+
+  MediaControl_InvalidPosition = PyErr_NewException("vlc.InvalidPosition", NULL, NULL);
+  PyModule_AddObject(m, "InvalidPosition", MediaControl_InvalidPosition);
+
+  MediaControl_PlaylistException = PyErr_NewException("vlc.PlaylistException", NULL, NULL);
+  PyModule_AddObject(m, "PlaylistException", MediaControl_PlaylistException);
+
+  /* Types */
+  Py_INCREF(&PyPosition_Type);
+  PyModule_AddObject(m, "Position", (PyObject *)&PyPosition_Type);
+  Py_INCREF(&MediaControl_Type);
+  PyModule_AddObject(m, "MediaControl", (PyObject *)&MediaControl_Type); 
+#ifdef VLCOBJECT_SUPPORT
+  Py_INCREF(&vlcObject_Type);
+  PyModule_AddObject(m, "Object", (PyObject *)&vlcObject_Type); 
+#endif
+
+  /* Constants */
+  PyModule_AddIntConstant(m, "AbsolutePosition", mediacontrol_AbsolutePosition);
+  PyModule_AddIntConstant(m, "RelativePosition", mediacontrol_RelativePosition);
+  PyModule_AddIntConstant(m, "ModuloPosition",   mediacontrol_ModuloPosition);
+
+  PyModule_AddIntConstant(m, "ByteCount",        mediacontrol_ByteCount);
+  PyModule_AddIntConstant(m, "SampleCount",      mediacontrol_SampleCount);
+  PyModule_AddIntConstant(m, "MediaTime",        mediacontrol_MediaTime);
+
+  PyModule_AddIntConstant(m, "PlayingStatus",    mediacontrol_PlayingStatus);
+  PyModule_AddIntConstant(m, "PauseStatus", mediacontrol_PauseStatus);
+  PyModule_AddIntConstant(m, "ForwardStatus", mediacontrol_ForwardStatus);
+  PyModule_AddIntConstant(m, "BackwardStatus", mediacontrol_BackwardStatus);
+  PyModule_AddIntConstant(m, "InitStatus", mediacontrol_InitStatus);
+  PyModule_AddIntConstant(m, "EndStatus", mediacontrol_EndStatus);
+  PyModule_AddIntConstant(m, "UndefinedStatus", mediacontrol_UndefinedStatus);
+
+
+}
+
+/* Make libpostproc happy... */
+void * fast_memcpy(void * to, const void * from, size_t len)
+{
+  return memcpy(to, from, len);
+}