2007年5月6日星期日

扩充gstreamer for python功能

最近编写一个能播放在线音乐的小工具,使用GStreamer做为播放引擎,前端用Python编写 ,使用了gst-python库,该对是对GStreamer的封装。
由于是播放在线音乐,播放前都有几秒的缓冲,程序将捕捉该事件,实时输出缓冲进度.添加事件回调函数on_message,当缓冲或播放结束等事件发生时,该函数会被调用:

self.player = gst.element_factory_make("playbin","player");
bus = self.player.get_bus();
bus.add_signal_watch();
bus.connect('message',self.on_message)

def on_message(self,bus,message);
if message.type == gst.MESSAGE_BUFFERING: #缓冲事件
struct = message.structure;
print "\nbuffering(%d)" % struct.get_int("buffer-percent");
esif: #处理其它事件


GStreamer在缓冲回调on_message时,将信息保存在message中的structure结构中的,该结构将根据不同的事件保存不同值,而gst-python暂时不提供从structure中取出缓冲进度的功能,所以就对gst-python进行了扩充,即为gst-python添加structure.get_int()方法.

下载gst-python-0.10.7,修改gststructure.override文件,该文件是处理structure的python封装,添加以下函数:

%%
override gst_structure_get_int kwargs
static PyObject *
_wrap_gst_structure_get_int(PyGObject *self,PyObject *args,PyObject *kwargs)
{
static char *kwlist[] = { "field" ,NULL };
int ret = -1;
char *field;
if (!PyArg_ParseTupleAndKeywords(args, kwargs,
"s:GstStructure.get_int",kwlist, &field))
return NULL;

gst_structure_get_int((GstStructure*)self->obj,field,(gint *)&ret);
return PyInt_FromLong(ret);
}
%%

override gst_structure_get_int kwargs
告诉代码生成器生成一个 gst_structure_get_int方法,kwargs告诉生成器该函数支持字典调用。

当python调用该函数时,所有参数都保存在args中,必须调用PyArg_ParseTupleAndKeywords解析参数:

if (!PyArg_ParseTupleAndKeywords(args, kwargs,
"s:GstStructure.get_int",kwlist, &field))

PyArg_ParseTupleAndKeywords的说明,可以参见:
http://www.python.org/doc/1.5.2p2/ext/parseTupleAndKeywords.html
http://www.python.org/doc/1.5.2p2/ext/parseTuple.html

gst_structure_get_int((GstStructure*)self->obj,field,(gint *)&ret);

将调用GStreamer的C接口,该方法将查询field的值保存到ret中。gst_structure_get_int的说明,可参见C接口说明:
http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer/html/gstreamer-GstStructure.html


最后调用Make编译gst-python,Make程序会调用代码生成器根据*.override生成gst.c文件。

代码生成器在gst.c中新增的内容:
static const PyMethodDef _PyGstStructure_methods[] = {
...
{ "get_int", (PyCFunction)_wrap_gst_structure_get_int, METH_VARARGS|METH_KEYWORDS,
NULL },
...
}
#line 65 "gststructure.override"
static PyObject *
_wrap_gst_structure_get_int(PyGObject *self,PyObject *py_key)
{
......
}

_PyGstStructure_methods保存python接口到c接口的映射,代码生成器是根据gst.defs文件生成_PyGstStructure_methods的内容,gst.defs文件已经生成好了,所以我们不必修改。

其中kwargs将生成上面的METH_KEYWORDS表示支持字典调用.另外在gststructure.override中添加的_wrap_gst_structure_get_int方法也会添加到gst.c中.

最后make会生成_gst.so文件,通过make install完成安装。

通过以上修改,就可以向上面例子那个通过调用struct.get_int("buffer-percent")来取得进度值了。

参考:

在 Python 中封装 GObject
用C语言扩展Python的功能
为python编写c/c++ 的extension