gstreamer/gst/pygstminiobject.c

382 lines
11 KiB
C
Raw Normal View History

/* -*- Mode: C; c-basic-offset: 4 -*-
* pygtk- Python bindings for the GTK toolkit.
* Copyright (C) 1998-2003 James Henstridge
*
* pygobject.c: wrapper for the GObject type.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
#define NO_IMPORT_PYGOBJECT
#define _INSIDE_PYGST_
#include "common.h"
#include "pygstminiobject.h"
#include "pygst.h"
#include <gst/gst.h>
static const gchar pygstminiobject_class_id[] = "PyGstMiniObject::class";
static GQuark pygstminiobject_class_key = 0;
/* static const gchar pygstminiobject_wrapper_id[] = "PyGstMiniObject::wrapper"; */
/* static GQuark pygstminiobject_wrapper_key = 0; */
static void pygstminiobject_dealloc (PyGstMiniObject * self);
/* static int pygstminiobject_traverse(PyGstMiniObject *self, visitproc visit, void *arg); */
/* static int pygstminiobject_clear(PyGstMiniObject *self); */
GST_DEBUG_CATEGORY_EXTERN (pygst_debug);
#define GST_CAT_DEFAULT pygst_debug
/**
* pygstminiobject_lookup_class:
* @gtype: the GType of the GstMiniObject subclass.
*
* This function looks up the wrapper class used to represent
* instances of a GstMiniObject represented by @gtype. If no wrapper class
* or interface has been registered for the given GType, then a new
* type will be created.
*
* Returns: The wrapper class for the GstMiniObject or NULL if the
* GType has no registered type and a new type couldn't be created
*/
PyTypeObject *
pygstminiobject_lookup_class (GType gtype)
{
PyTypeObject *py_type = NULL;
GType ctype = gtype;
while (!py_type && ctype) {
py_type = g_type_get_qdata (ctype, pygstminiobject_class_key);
ctype = g_type_parent (ctype);
}
if (!ctype)
g_error ("Couldn't find a good base type!!");
return py_type;
}
/**
* pygstminiobject_register_class:
* @dict: the module dictionary. A reference to the type will be stored here.
* @type_name: not used ?
* @gtype: the GType of the Gstminiobject subclass.
* @type: the Python type object for this wrapper.
* @bases: a tuple of Python type objects that are the bases of this type.
*
* This function is used to register a Python type as the wrapper for
* a particular Gstminiobject subclass. It will also insert a reference to
* the wrapper class into the module dictionary passed as a reference,
* which simplifies initialisation.
*/
void
pygstminiobject_register_class (PyObject * dict, const gchar * type_name,
GType gtype, PyTypeObject * type, PyObject * bases)
{
PyObject *o;
const char *class_name, *s;
if (!pygstminiobject_class_key)
pygstminiobject_class_key =
g_quark_from_static_string (pygstminiobject_class_id);
class_name = type->tp_name;
s = strrchr (class_name, '.');
if (s != NULL)
class_name = s + 1;
type->ob_type = &PyType_Type;
type->tp_alloc = PyType_GenericAlloc;
type->tp_new = PyType_GenericNew;
if (bases) {
type->tp_bases = bases;
type->tp_base = (PyTypeObject *) PyTuple_GetItem (bases, 0);
}
if (PyType_Ready (type) < 0) {
g_warning ("couldn't make the type `%s' ready", type->tp_name);
return;
}
if (gtype) {
o = pyg_type_wrapper_new (gtype);
PyDict_SetItemString (type->tp_dict, "__gtype__", o);
Py_DECREF (o);
/* stash a pointer to the python class with the GType */
Py_INCREF (type);
g_type_set_qdata (gtype, pygstminiobject_class_key, type);
}
PyDict_SetItemString (dict, (char *) class_name, (PyObject *) type);
}
void
pygstminiobject_register_wrapper (PyObject * self)
{
}
/**
* pygstminiobject_new:
* @obj: a GstMiniObject instance.
*
* This function gets a reference to a wrapper for the given GstMiniObject
* instance. A new wrapper will always be created.
*
* Returns: a reference to the wrapper for the GstMiniObject.
*/
PyObject *
pygstminiobject_new (GstMiniObject * obj)
{
PyGstMiniObject *self = NULL;
PyGILState_STATE state;
PyTypeObject *tp = NULL;
if (obj == NULL) {
Py_INCREF (Py_None);
return Py_None;
}
/* since mini objects cannot notify us when they get destroyed, we
* can't use a global hash to map GMO to PyO, and have to create a new
* Python object every time we see it */
tp = pygstminiobject_lookup_class (G_OBJECT_TYPE (obj));
GST_DEBUG ("have to create wrapper for object %p", obj);
if (!tp)
g_warning ("Couldn't get class for type object : %p", obj);
if (tp->tp_flags & Py_TPFLAGS_HEAPTYPE) {
GST_INFO ("Increment refcount %p", tp);
Py_INCREF (tp);
}
state = pyg_gil_state_ensure ();
self = PyObject_New (PyGstMiniObject, tp);
pyg_gil_state_release (state);
if (self == NULL)
return NULL;
self->obj = gst_mini_object_ref (obj);
self->inst_dict = NULL;
self->weakreflist = NULL;
GST_DEBUG ("created Python object %p for GstMiniObject %p [ref:%d]",
self, obj, GST_MINI_OBJECT_REFCOUNT_VALUE (obj));
return (PyObject *) self;
}
static void
pygstminiobject_dealloc (PyGstMiniObject * self)
{
PyGILState_STATE state;
g_return_if_fail (self != NULL);
GST_DEBUG ("At the beginning %p", self);
state = pyg_gil_state_ensure ();
if (self->obj) {
GST_DEBUG ("PyO %p unreffing GstMiniObject %p [ref:%d]", self,
self->obj, GST_MINI_OBJECT_REFCOUNT_VALUE (self->obj));
gst_mini_object_unref (self->obj);
GST_DEBUG ("setting self %p -> obj to NULL", self);
self->obj = NULL;
}
if (self->inst_dict) {
Py_DECREF (self->inst_dict);
self->inst_dict = NULL;
}
self->ob_type->tp_free ((PyObject *) self);
pyg_gil_state_release (state);
GST_DEBUG ("At the end %p", self);
}
static int
pygstminiobject_compare (PyGstMiniObject * self, PyGstMiniObject * v)
{
if (self->obj == v->obj)
return 0;
if (self->obj > v->obj)
return -1;
return 1;
}
static long
pygstminiobject_hash (PyGstMiniObject * self)
{
return (long) self->obj;
}
static PyObject *
pygstminiobject_repr (PyGstMiniObject * self)
{
gchar buf[256];
g_snprintf (buf, sizeof (buf),
"<%s mini-object (%s) at 0x%lx>",
self->ob_type->tp_name,
self->obj ? G_OBJECT_TYPE_NAME (self->obj) : "uninitialized",
(long) self);
return PyString_FromString (buf);
}
static void
pygstminiobject_free (PyObject * op)
{
PyObject_FREE (op);
}
/* ---------------- PyGstMiniObject methods ----------------- */
static int
pygstminiobject_init (PyGstMiniObject * self, PyObject * args,
PyObject * kwargs)
{
GType object_type;
GstMiniObjectClass *class;
if (!PyArg_ParseTuple (args, ":GstMiniObject.__init__", &object_type))
return -1;
object_type = pyg_type_from_object ((PyObject *) self);
if (!object_type)
return -1;
if (G_TYPE_IS_ABSTRACT (object_type)) {
PyErr_Format (PyExc_TypeError, "cannot create instance of abstract "
"(non-instantiable) type `%s'", g_type_name (object_type));
return -1;
}
if ((class = g_type_class_ref (object_type)) == NULL) {
PyErr_SetString (PyExc_TypeError,
"could not get a reference to type class");
return -1;
}
self->obj = gst_mini_object_new (object_type);
if (self->obj == NULL)
PyErr_SetString (PyExc_RuntimeError, "could not create object");
g_type_class_unref (class);
return (self->obj) ? 0 : -1;
}
static PyObject *
pygstminiobject__gstminiobject_init__ (PyGstMiniObject * self, PyObject * args,
PyObject * kwargs)
{
if (pygstminiobject_init (self, args, kwargs) < 0)
return NULL;
Py_INCREF (Py_None);
return Py_None;
}
static PyObject *
pygstminiobject_copy (PyGstMiniObject * self, PyObject * args)
{
return pygstminiobject_new (gst_mini_object_copy (self->obj));
}
static PyMethodDef pygstminiobject_methods[] = {
{"__gstminiobject_init__",
(PyCFunction) pygstminiobject__gstminiobject_init__,
METH_VARARGS | METH_KEYWORDS},
{"copy", (PyCFunction) pygstminiobject_copy, METH_VARARGS,
"Copies the miniobject"},
{NULL, NULL, 0}
};
static PyObject *
pygstminiobject_get_dict (PyGstMiniObject * self, void *closure)
{
if (self->inst_dict == NULL) {
self->inst_dict = PyDict_New ();
if (self->inst_dict == NULL)
return NULL;
}
Py_INCREF (self->inst_dict);
return self->inst_dict;
}
static PyObject *
pygstminiobject_get_refcount (PyGstMiniObject * self, void *closure)
{
return PyInt_FromLong (GST_MINI_OBJECT_REFCOUNT_VALUE (self->obj));
}
static PyObject *
pygstminiobject_get_flags (PyGstMiniObject * self, void *closure)
{
return PyInt_FromLong (GST_MINI_OBJECT_FLAGS (self->obj));
}
static PyGetSetDef pygstminiobject_getsets[] = {
{"__dict__", (getter) pygstminiobject_get_dict, (setter) 0},
{"__grefcount__", (getter) pygstminiobject_get_refcount, (setter) 0,},
{"flags", (getter) pygstminiobject_get_flags, (setter) 0,},
{NULL, 0, 0}
};
PyTypeObject PyGstMiniObject_Type = {
PyObject_HEAD_INIT (NULL)
0, /* ob_size */
"gst.MiniObject", /* tp_name */
sizeof (PyGstMiniObject), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
(destructor) pygstminiobject_dealloc, /* tp_dealloc */
(printfunc) 0, /* tp_print */
(getattrfunc) 0, /* tp_getattr */
(setattrfunc) 0, /* tp_setattr */
(cmpfunc) pygstminiobject_compare, /* tp_compare */
(reprfunc) pygstminiobject_repr, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
(hashfunc) pygstminiobject_hash, /* tp_hash */
(ternaryfunc) 0, /* tp_call */
(reprfunc) 0, /* tp_str */
(getattrofunc) 0, /* tp_getattro */
(setattrofunc) 0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
NULL, /* Documentation string */
(traverseproc) 0, /* tp_traverse */
(inquiry) 0, /* tp_clear */
(richcmpfunc) 0, /* tp_richcompare */
offsetof (PyGstMiniObject, weakreflist), /* tp_weaklistoffset */
(getiterfunc) 0, /* tp_iter */
(iternextfunc) 0, /* tp_iternext */
pygstminiobject_methods, /* tp_methods */
0, /* tp_members */
pygstminiobject_getsets, /* tp_getset */
(PyTypeObject *) 0, /* tp_base */
(PyObject *) 0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
offsetof (PyGstMiniObject, inst_dict), /* tp_dictoffset */
(initproc) pygstminiobject_init, /* tp_init */
(allocfunc) 0, /* tp_alloc */
(newfunc) 0, /* tp_new */
(freefunc) pygstminiobject_free, /* tp_free */
(inquiry) 0, /* tp_is_gc */
(PyObject *) 0, /* tp_bases */
};