This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/extern/audaspace/bindings/python/PyHandle.cpp
Joerg Mueller 986267300b Audaspace: Moving audaspace 1.3 into extern.
Deleting the old internal audaspace.

Major changes from there are:
- The whole library was refactored to use C++11.
- Many stability and performance improvements.
- Major Python API refactor:
 - Most requested: Play self generated sounds using numpy arrays.
 - For games: Sound list, random sounds and dynamic music.
 - Writing sounds to files.
 - Sequencing API.
 - Opening sound devices, eg. Jack.
- Ability to choose different OpenAL devices in the user settings.
2017-08-18 08:24:12 +02:00

1127 lines
26 KiB
C++

/*******************************************************************************
* 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 <memory>
#include <structmember.h>
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<std::shared_ptr<IHandle>*>(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<std::shared_ptr<IHandle>*>(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<std::shared_ptr<IHandle>*>(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<std::shared_ptr<IHandle>*>(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<I3DHandle*>(reinterpret_cast<std::shared_ptr<IHandle>*>(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<I3DHandle*>(reinterpret_cast<std::shared_ptr<IHandle>*>(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<I3DHandle*>(reinterpret_cast<std::shared_ptr<IHandle>*>(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<I3DHandle*>(reinterpret_cast<std::shared_ptr<IHandle>*>(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<I3DHandle*>(reinterpret_cast<std::shared_ptr<IHandle>*>(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<I3DHandle*>(reinterpret_cast<std::shared_ptr<IHandle>*>(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<I3DHandle*>(reinterpret_cast<std::shared_ptr<IHandle>*>(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<I3DHandle*>(reinterpret_cast<std::shared_ptr<IHandle>*>(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<I3DHandle*>(reinterpret_cast<std::shared_ptr<IHandle>*>(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<I3DHandle*>(reinterpret_cast<std::shared_ptr<IHandle>*>(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<I3DHandle*>(reinterpret_cast<std::shared_ptr<IHandle>*>(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<I3DHandle*>(reinterpret_cast<std::shared_ptr<IHandle>*>(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<std::shared_ptr<IHandle>*>(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<std::shared_ptr<IHandle>*>(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<I3DHandle*>(reinterpret_cast<std::shared_ptr<IHandle>*>(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<I3DHandle*>(reinterpret_cast<std::shared_ptr<IHandle>*>(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<std::shared_ptr<IHandle>*>(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<std::shared_ptr<IHandle>*>(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<I3DHandle*>(reinterpret_cast<std::shared_ptr<IHandle>*>(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<I3DHandle*>(reinterpret_cast<std::shared_ptr<IHandle>*>(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<std::shared_ptr<IHandle>*>(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<std::shared_ptr<IHandle>*>(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<std::shared_ptr<IHandle>*>(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<std::shared_ptr<IHandle>*>(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<I3DHandle*>(reinterpret_cast<std::shared_ptr<IHandle>*>(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<I3DHandle*>(reinterpret_cast<std::shared_ptr<IHandle>*>(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<std::shared_ptr<IHandle>*>(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<I3DHandle*>(reinterpret_cast<std::shared_ptr<IHandle>*>(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<I3DHandle*>(reinterpret_cast<std::shared_ptr<IHandle>*>(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<std::shared_ptr<IHandle>*>(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<std::shared_ptr<IHandle>*>(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<I3DHandle*>(reinterpret_cast<std::shared_ptr<IHandle>*>(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<I3DHandle*>(reinterpret_cast<std::shared_ptr<IHandle>*>(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<I3DHandle*>(reinterpret_cast<std::shared_ptr<IHandle>*>(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<I3DHandle*>(reinterpret_cast<std::shared_ptr<IHandle>*>(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);
}