/* -*- 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 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 */ };