/******************************************************************************* * Copyright 2009-2016 Jörg Müller * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ #include "PyHandle.h" #include "devices/IHandle.h" #include "devices/I3DHandle.h" #include "Exception.h" #include #include using namespace aud; extern PyObject* AUDError; static const char* device_not_3d_error = "Device is not a 3D device!"; static void Handle_dealloc(Handle* self) { if(self->handle) delete reinterpret_cast*>(self->handle); Py_TYPE(self)->tp_free((PyObject *)self); } PyDoc_STRVAR(M_aud_Handle_pause_doc, "pause()\n\n" "Pauses playback.\n\n" ":return: Whether the action succeeded.\n" ":rtype: bool"); static PyObject * Handle_pause(Handle* self) { try { return PyBool_FromLong((long)(*reinterpret_cast*>(self->handle))->pause()); } catch(Exception& e) { PyErr_SetString(AUDError, e.what()); return nullptr; } } PyDoc_STRVAR(M_aud_Handle_resume_doc, "resume()\n\n" "Resumes playback.\n\n" ":return: Whether the action succeeded.\n" ":rtype: bool"); static PyObject * Handle_resume(Handle* self) { try { return PyBool_FromLong((long)(*reinterpret_cast*>(self->handle))->resume()); } catch(Exception& e) { PyErr_SetString(AUDError, e.what()); return nullptr; } } PyDoc_STRVAR(M_aud_Handle_stop_doc, "stop()\n\n" "Stops playback.\n\n" ":return: Whether the action succeeded.\n" ":rtype: bool\n\n" ".. note:: This makes the handle invalid."); static PyObject * Handle_stop(Handle* self) { try { return PyBool_FromLong((long)(*reinterpret_cast*>(self->handle))->stop()); } catch(Exception& e) { PyErr_SetString(AUDError, e.what()); return nullptr; } } static PyMethodDef Handle_methods[] = { {"pause", (PyCFunction)Handle_pause, METH_NOARGS, M_aud_Handle_pause_doc }, {"resume", (PyCFunction)Handle_resume, METH_NOARGS, M_aud_Handle_resume_doc }, {"stop", (PyCFunction)Handle_stop, METH_NOARGS, M_aud_Handle_stop_doc }, {nullptr} /* Sentinel */ }; PyDoc_STRVAR(M_aud_Handle_attenuation_doc, "This factor is used for distance based attenuation of the " "source.\n\n" ".. seealso:: :attr:`Device.distance_model`"); static PyObject * Handle_get_attenuation(Handle* self, void* nothing) { try { I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); if(handle) { return Py_BuildValue("f", handle->getAttenuation()); } else { PyErr_SetString(AUDError, device_not_3d_error); return nullptr; } } catch(Exception& e) { PyErr_SetString(AUDError, e.what()); return nullptr; } } static int Handle_set_attenuation(Handle* self, PyObject* args, void* nothing) { float factor; if(!PyArg_Parse(args, "f:attenuation", &factor)) return -1; try { I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); if(handle) { if(handle->setAttenuation(factor)) return 0; PyErr_SetString(AUDError, "Couldn't set the attenuation!"); } else PyErr_SetString(AUDError, device_not_3d_error); } catch(Exception& e) { PyErr_SetString(AUDError, e.what()); } return -1; } PyDoc_STRVAR(M_aud_Handle_cone_angle_inner_doc, "The opening angle of the inner cone of the source. If the cone " "values of a source are set there are two (audible) cones with " "the apex at the :attr:`location` of the source and with infinite " "height, heading in the direction of the source's " ":attr:`orientation`.\n" "In the inner cone the volume is normal. Outside the outer cone " "the volume will be :attr:`cone_volume_outer` and in the area " "between the volume will be interpolated linearly."); static PyObject * Handle_get_cone_angle_inner(Handle* self, void* nothing) { try { I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); if(handle) { return Py_BuildValue("f", handle->getConeAngleInner()); } else { PyErr_SetString(AUDError, device_not_3d_error); return nullptr; } } catch(Exception& e) { PyErr_SetString(AUDError, e.what()); return nullptr; } } static int Handle_set_cone_angle_inner(Handle* self, PyObject* args, void* nothing) { float angle; if(!PyArg_Parse(args, "f:cone_angle_inner", &angle)) return -1; try { I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); if(handle) { if(handle->setConeAngleInner(angle)) return 0; PyErr_SetString(AUDError, "Couldn't set the cone inner angle!"); } else PyErr_SetString(AUDError, device_not_3d_error); } catch(Exception& e) { PyErr_SetString(AUDError, e.what()); } return -1; } PyDoc_STRVAR(M_aud_Handle_cone_angle_outer_doc, "The opening angle of the outer cone of the source.\n\n" ".. seealso:: :attr:`cone_angle_inner`"); static PyObject * Handle_get_cone_angle_outer(Handle* self, void* nothing) { try { I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); if(handle) { return Py_BuildValue("f", handle->getConeAngleOuter()); } else { PyErr_SetString(AUDError, device_not_3d_error); return nullptr; } } catch(Exception& e) { PyErr_SetString(AUDError, e.what()); return nullptr; } } static int Handle_set_cone_angle_outer(Handle* self, PyObject* args, void* nothing) { float angle; if(!PyArg_Parse(args, "f:cone_angle_outer", &angle)) return -1; try { I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); if(handle) { if(handle->setConeAngleOuter(angle)) return 0; PyErr_SetString(AUDError, "Couldn't set the cone outer angle!"); } else PyErr_SetString(AUDError, device_not_3d_error); } catch(Exception& e) { PyErr_SetString(AUDError, e.what()); } return -1; } PyDoc_STRVAR(M_aud_Handle_cone_volume_outer_doc, "The volume outside the outer cone of the source.\n\n" ".. seealso:: :attr:`cone_angle_inner`"); static PyObject * Handle_get_cone_volume_outer(Handle* self, void* nothing) { try { I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); if(handle) { return Py_BuildValue("f", handle->getConeVolumeOuter()); } else { PyErr_SetString(AUDError, device_not_3d_error); return nullptr; } } catch(Exception& e) { PyErr_SetString(AUDError, e.what()); return nullptr; } } static int Handle_set_cone_volume_outer(Handle* self, PyObject* args, void* nothing) { float volume; if(!PyArg_Parse(args, "f:cone_volume_outer", &volume)) return -1; try { I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); if(handle) { if(handle->setConeVolumeOuter(volume)) return 0; PyErr_SetString(AUDError, "Couldn't set the cone outer volume!"); } else PyErr_SetString(AUDError, device_not_3d_error); } catch(Exception& e) { PyErr_SetString(AUDError, e.what()); } return -1; } PyDoc_STRVAR(M_aud_Handle_distance_maximum_doc, "The maximum distance of the source.\n" "If the listener is further away the source volume will be 0.\n\n" ".. seealso:: :attr:`Device.distance_model`"); static PyObject * Handle_get_distance_maximum(Handle* self, void* nothing) { try { I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); if(handle) { return Py_BuildValue("f", handle->getDistanceMaximum()); } else { PyErr_SetString(AUDError, device_not_3d_error); return nullptr; } } catch(Exception& e) { PyErr_SetString(AUDError, e.what()); return nullptr; } } static int Handle_set_distance_maximum(Handle* self, PyObject* args, void* nothing) { float distance; if(!PyArg_Parse(args, "f:distance_maximum", &distance)) return -1; try { I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); if(handle) { if(handle->setDistanceMaximum(distance)) return 0; PyErr_SetString(AUDError, "Couldn't set the maximum distance!"); } else PyErr_SetString(AUDError, device_not_3d_error); } catch(Exception& e) { PyErr_SetString(AUDError, e.what()); } return -1; } PyDoc_STRVAR(M_aud_Handle_distance_reference_doc, "The reference distance of the source.\n" "At this distance the volume will be exactly :attr:`volume`.\n\n" ".. seealso:: :attr:`Device.distance_model`"); static PyObject * Handle_get_distance_reference(Handle* self, void* nothing) { try { I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); if(handle) { return Py_BuildValue("f", handle->getDistanceReference()); } else { PyErr_SetString(AUDError, device_not_3d_error); return nullptr; } } catch(Exception& e) { PyErr_SetString(AUDError, e.what()); return nullptr; } } static int Handle_set_distance_reference(Handle* self, PyObject* args, void* nothing) { float distance; if(!PyArg_Parse(args, "f:distance_reference", &distance)) return -1; try { I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); if(handle) { if(handle->setDistanceReference(distance)) return 0; PyErr_SetString(AUDError, "Couldn't set the reference distance!"); } else PyErr_SetString(AUDError, device_not_3d_error); } catch(Exception& e) { PyErr_SetString(AUDError, e.what()); } return -1; } PyDoc_STRVAR(M_aud_Handle_keep_doc, "Whether the sound should be kept paused in the device when its " "end is reached.\n" "This can be used to seek the sound to some position and start " "playback again.\n\n" ".. warning:: If this is set to true and you forget stopping this " "equals a memory leak as the handle exists until the device is " "destroyed."); static PyObject * Handle_get_keep(Handle* self, void* nothing) { try { return PyBool_FromLong((long)(*reinterpret_cast*>(self->handle))->getKeep()); } catch(Exception& e) { PyErr_SetString(AUDError, e.what()); return nullptr; } } static int Handle_set_keep(Handle* self, PyObject* args, void* nothing) { if(!PyBool_Check(args)) { PyErr_SetString(PyExc_TypeError, "keep is not a boolean!"); return -1; } bool keep = args == Py_True; try { if((*reinterpret_cast*>(self->handle))->setKeep(keep)) return 0; PyErr_SetString(AUDError, "Couldn't set keep of the sound!"); } catch(Exception& e) { PyErr_SetString(AUDError, e.what()); } return -1; } PyDoc_STRVAR(M_aud_Handle_location_doc, "The source's location in 3D space, a 3D tuple of floats."); static PyObject * Handle_get_location(Handle* self, void* nothing) { try { I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); if(handle) { Vector3 v = handle->getLocation(); return Py_BuildValue("(fff)", v.x(), v.y(), v.z()); } else { PyErr_SetString(AUDError, device_not_3d_error); } } catch(Exception& e) { PyErr_SetString(AUDError, e.what()); } return nullptr; } static int Handle_set_location(Handle* self, PyObject* args, void* nothing) { float x, y, z; if(!PyArg_Parse(args, "(fff):location", &x, &y, &z)) return -1; try { I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); if(handle) { Vector3 location(x, y, z); if(handle->setLocation(location)) return 0; PyErr_SetString(AUDError, "Location couldn't be set!"); } else PyErr_SetString(AUDError, device_not_3d_error); } catch(Exception& e) { PyErr_SetString(AUDError, e.what()); } return -1; } PyDoc_STRVAR(M_aud_Handle_loop_count_doc, "The (remaining) loop count of the sound. A negative value indicates infinity."); static PyObject * Handle_get_loop_count(Handle* self, void* nothing) { try { return Py_BuildValue("i", (*reinterpret_cast*>(self->handle))->getLoopCount()); } catch(Exception& e) { PyErr_SetString(AUDError, e.what()); return nullptr; } } static int Handle_set_loop_count(Handle* self, PyObject* args, void* nothing) { int loops; if(!PyArg_Parse(args, "i:loop_count", &loops)) return -1; try { if((*reinterpret_cast*>(self->handle))->setLoopCount(loops)) return 0; PyErr_SetString(AUDError, "Couldn't set the loop count!"); } catch(Exception& e) { PyErr_SetString(AUDError, e.what()); } return -1; } PyDoc_STRVAR(M_aud_Handle_orientation_doc, "The source's orientation in 3D space as quaternion, a 4 float tuple."); static PyObject * Handle_get_orientation(Handle* self, void* nothing) { try { I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); if(handle) { Quaternion o = handle->getOrientation(); return Py_BuildValue("(ffff)", o.w(), o.x(), o.y(), o.z()); } else { PyErr_SetString(AUDError, device_not_3d_error); } } catch(Exception& e) { PyErr_SetString(AUDError, e.what()); } return nullptr; } static int Handle_set_orientation(Handle* self, PyObject* args, void* nothing) { float w, x, y, z; if(!PyArg_Parse(args, "(ffff):orientation", &w, &x, &y, &z)) return -1; try { I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); if(handle) { Quaternion orientation(w, x, y, z); if(handle->setOrientation(orientation)) return 0; PyErr_SetString(AUDError, "Couldn't set the orientation!"); } else PyErr_SetString(AUDError, device_not_3d_error); } catch(Exception& e) { PyErr_SetString(AUDError, e.what()); } return -1; } PyDoc_STRVAR(M_aud_Handle_pitch_doc, "The pitch of the sound."); static PyObject * Handle_get_pitch(Handle* self, void* nothing) { try { return Py_BuildValue("f", (*reinterpret_cast*>(self->handle))->getPitch()); } catch(Exception& e) { PyErr_SetString(AUDError, e.what()); return nullptr; } } static int Handle_set_pitch(Handle* self, PyObject* args, void* nothing) { float pitch; if(!PyArg_Parse(args, "f:pitch", &pitch)) return -1; try { if((*reinterpret_cast*>(self->handle))->setPitch(pitch)) return 0; PyErr_SetString(AUDError, "Couldn't set the sound pitch!"); } catch(Exception& e) { PyErr_SetString(AUDError, e.what()); } return -1; } PyDoc_STRVAR(M_aud_Handle_position_doc, "The playback position of the sound in seconds."); static PyObject * Handle_get_position(Handle* self, void* nothing) { try { return Py_BuildValue("f", (*reinterpret_cast*>(self->handle))->getPosition()); } catch(Exception& e) { PyErr_SetString(AUDError, e.what()); return nullptr; } } static int Handle_set_position(Handle* self, PyObject* args, void* nothing) { float position; if(!PyArg_Parse(args, "f:position", &position)) return -1; try { if((*reinterpret_cast*>(self->handle))->seek(position)) return 0; PyErr_SetString(AUDError, "Couldn't seek the sound!"); } catch(Exception& e) { PyErr_SetString(AUDError, e.what()); } return -1; } PyDoc_STRVAR(M_aud_Handle_relative_doc, "Whether the source's location, velocity and orientation is relative or absolute to the listener."); static PyObject * Handle_get_relative(Handle* self, void* nothing) { try { I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); if(handle) { return PyBool_FromLong((long)handle->isRelative()); } else { PyErr_SetString(AUDError, device_not_3d_error); } } catch(Exception& e) { PyErr_SetString(AUDError, e.what()); } return nullptr; } static int Handle_set_relative(Handle* self, PyObject* args, void* nothing) { if(!PyBool_Check(args)) { PyErr_SetString(PyExc_TypeError, "Value is not a boolean!"); return -1; } bool relative = (args == Py_True); try { I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); if(handle) { if(handle->setRelative(relative)) return 0; PyErr_SetString(AUDError, "Couldn't set the relativeness!"); } else PyErr_SetString(AUDError, device_not_3d_error); } catch(Exception& e) { PyErr_SetString(AUDError, e.what()); } return -1; } PyDoc_STRVAR(M_aud_Handle_status_doc, "Whether the sound is playing, paused or stopped (=invalid)."); static PyObject * Handle_get_status(Handle* self, void* nothing) { try { return PyBool_FromLong((long)(*reinterpret_cast*>(self->handle))->getStatus()); } catch(Exception& e) { PyErr_SetString(AUDError, e.what()); return nullptr; } } PyDoc_STRVAR(M_aud_Handle_velocity_doc, "The source's velocity in 3D space, a 3D tuple of floats."); static PyObject * Handle_get_velocity(Handle* self, void* nothing) { try { I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); if(handle) { Vector3 v = handle->getVelocity(); return Py_BuildValue("(fff)", v.x(), v.y(), v.z()); } else { PyErr_SetString(AUDError, device_not_3d_error); } } catch(Exception& e) { PyErr_SetString(AUDError, e.what()); } return nullptr; } static int Handle_set_velocity(Handle* self, PyObject* args, void* nothing) { float x, y, z; if(!PyArg_Parse(args, "(fff):velocity", &x, &y, &z)) return -1; try { I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); if(handle) { Vector3 velocity(x, y, z); if(handle->setVelocity(velocity)) return 0; PyErr_SetString(AUDError, "Couldn't set the velocity!"); } else PyErr_SetString(AUDError, device_not_3d_error); } catch(Exception& e) { PyErr_SetString(AUDError, e.what()); } return -1; } PyDoc_STRVAR(M_aud_Handle_volume_doc, "The volume of the sound."); static PyObject * Handle_get_volume(Handle* self, void* nothing) { try { return Py_BuildValue("f", (*reinterpret_cast*>(self->handle))->getVolume()); } catch(Exception& e) { PyErr_SetString(AUDError, e.what()); return nullptr; } } static int Handle_set_volume(Handle* self, PyObject* args, void* nothing) { float volume; if(!PyArg_Parse(args, "f:volume", &volume)) return -1; try { if((*reinterpret_cast*>(self->handle))->setVolume(volume)) return 0; PyErr_SetString(AUDError, "Couldn't set the sound volume!"); } catch(Exception& e) { PyErr_SetString(AUDError, e.what()); } return -1; } PyDoc_STRVAR(M_aud_Handle_volume_maximum_doc, "The maximum volume of the source.\n\n" ".. seealso:: :attr:`Device.distance_model`"); static PyObject * Handle_get_volume_maximum(Handle* self, void* nothing) { try { I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); if(handle) { return Py_BuildValue("f", handle->getVolumeMaximum()); } else { PyErr_SetString(AUDError, device_not_3d_error); return nullptr; } } catch(Exception& e) { PyErr_SetString(AUDError, e.what()); return nullptr; } } static int Handle_set_volume_maximum(Handle* self, PyObject* args, void* nothing) { float volume; if(!PyArg_Parse(args, "f:volume_maximum", &volume)) return -1; try { I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); if(handle) { if(handle->setVolumeMaximum(volume)) return 0; PyErr_SetString(AUDError, "Couldn't set the maximum volume!"); } else PyErr_SetString(AUDError, device_not_3d_error); } catch(Exception& e) { PyErr_SetString(AUDError, e.what()); } return -1; } PyDoc_STRVAR(M_aud_Handle_volume_minimum_doc, "The minimum volume of the source.\n\n" ".. seealso:: :attr:`Device.distance_model`"); static PyObject * Handle_get_volume_minimum(Handle* self, void* nothing) { try { I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); if(handle) { return Py_BuildValue("f", handle->getVolumeMinimum()); } else { PyErr_SetString(AUDError, device_not_3d_error); return nullptr; } } catch(Exception& e) { PyErr_SetString(AUDError, e.what()); return nullptr; } } static int Handle_set_volume_minimum(Handle* self, PyObject* args, void* nothing) { float volume; if(!PyArg_Parse(args, "f:volume_minimum", &volume)) return -1; try { I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); if(handle) { if(handle->setVolumeMinimum(volume)) return 0; PyErr_SetString(AUDError, "Couldn't set the minimum volume!"); } else PyErr_SetString(AUDError, device_not_3d_error); } catch(Exception& e) { PyErr_SetString(AUDError, e.what()); } return -1; } static PyGetSetDef Handle_properties[] = { {(char*)"attenuation", (getter)Handle_get_attenuation, (setter)Handle_set_attenuation, M_aud_Handle_attenuation_doc, nullptr }, {(char*)"cone_angle_inner", (getter)Handle_get_cone_angle_inner, (setter)Handle_set_cone_angle_inner, M_aud_Handle_cone_angle_inner_doc, nullptr }, {(char*)"cone_angle_outer", (getter)Handle_get_cone_angle_outer, (setter)Handle_set_cone_angle_outer, M_aud_Handle_cone_angle_outer_doc, nullptr }, {(char*)"cone_volume_outer", (getter)Handle_get_cone_volume_outer, (setter)Handle_set_cone_volume_outer, M_aud_Handle_cone_volume_outer_doc, nullptr }, {(char*)"distance_maximum", (getter)Handle_get_distance_maximum, (setter)Handle_set_distance_maximum, M_aud_Handle_distance_maximum_doc, nullptr }, {(char*)"distance_reference", (getter)Handle_get_distance_reference, (setter)Handle_set_distance_reference, M_aud_Handle_distance_reference_doc, nullptr }, {(char*)"keep", (getter)Handle_get_keep, (setter)Handle_set_keep, M_aud_Handle_keep_doc, nullptr }, {(char*)"location", (getter)Handle_get_location, (setter)Handle_set_location, M_aud_Handle_location_doc, nullptr }, {(char*)"loop_count", (getter)Handle_get_loop_count, (setter)Handle_set_loop_count, M_aud_Handle_loop_count_doc, nullptr }, {(char*)"orientation", (getter)Handle_get_orientation, (setter)Handle_set_orientation, M_aud_Handle_orientation_doc, nullptr }, {(char*)"pitch", (getter)Handle_get_pitch, (setter)Handle_set_pitch, M_aud_Handle_pitch_doc, nullptr }, {(char*)"position", (getter)Handle_get_position, (setter)Handle_set_position, M_aud_Handle_position_doc, nullptr }, {(char*)"relative", (getter)Handle_get_relative, (setter)Handle_set_relative, M_aud_Handle_relative_doc, nullptr }, {(char*)"status", (getter)Handle_get_status, nullptr, M_aud_Handle_status_doc, nullptr }, {(char*)"velocity", (getter)Handle_get_velocity, (setter)Handle_set_velocity, M_aud_Handle_velocity_doc, nullptr }, {(char*)"volume", (getter)Handle_get_volume, (setter)Handle_set_volume, M_aud_Handle_volume_doc, nullptr }, {(char*)"volume_maximum", (getter)Handle_get_volume_maximum, (setter)Handle_set_volume_maximum, M_aud_Handle_volume_maximum_doc, nullptr }, {(char*)"volume_minimum", (getter)Handle_get_volume_minimum, (setter)Handle_set_volume_minimum, M_aud_Handle_volume_minimum_doc, nullptr }, {nullptr} /* Sentinel */ }; PyDoc_STRVAR(M_aud_Handle_doc, "Handle objects are playback handles that can be used to control " "playback of a sound. If a sound is played back multiple times " "then there are as many handles."); static PyTypeObject HandleType = { PyVarObject_HEAD_INIT(nullptr, 0) "aud.Handle", /* tp_name */ sizeof(Handle), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)Handle_dealloc,/* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_reserved */ 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, /* tp_flags */ M_aud_Handle_doc, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Handle_methods, /* tp_methods */ 0, /* tp_members */ Handle_properties, /* 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 */ 0, /* tp_new */ }; AUD_API PyObject* Handle_empty() { return HandleType.tp_alloc(&HandleType, 0); } AUD_API Handle*checkHandle(PyObject* handle) { if(!PyObject_TypeCheck(handle, &HandleType)) { PyErr_SetString(PyExc_TypeError, "Object is not of type Handle!"); return nullptr; } return (Handle*)handle; } bool initializeHandle() { return PyType_Ready(&HandleType) >= 0; } void addHandleToModule(PyObject* module) { Py_INCREF(&HandleType); PyModule_AddObject(module, "Handle", (PyObject *)&HandleType); }