diff options
Diffstat (limited to 'extern/audaspace/bindings/python/PySequence.cpp')
-rw-r--r-- | extern/audaspace/bindings/python/PySequence.cpp | 655 |
1 files changed, 655 insertions, 0 deletions
diff --git a/extern/audaspace/bindings/python/PySequence.cpp b/extern/audaspace/bindings/python/PySequence.cpp new file mode 100644 index 00000000000..d4773c743ee --- /dev/null +++ b/extern/audaspace/bindings/python/PySequence.cpp @@ -0,0 +1,655 @@ +/******************************************************************************* + * 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 "PySequence.h" + +#include "PySound.h" +#include "PySequenceEntry.h" + +#include "sequence/AnimateableProperty.h" +#include "sequence/Sequence.h" +#include "Exception.h" + +#include <vector> +#include <structmember.h> + +using aud::Channels; +using aud::DistanceModel; +using aud::Exception; +using aud::ISound; +using aud::AnimateableProperty; +using aud::AnimateablePropertyType; +using aud::Specs; + +extern PyObject* AUDError; + +// ==================================================================== + +static void +Sequence_dealloc(Sequence* self) +{ + if(self->sequence) + delete reinterpret_cast<std::shared_ptr<aud::Sequence>*>(self->sequence); + Py_TYPE(self)->tp_free((PyObject *)self); +} + +static PyObject * +Sequence_new(PyTypeObject* type, PyObject* args, PyObject* kwds) +{ + Sequence* self; + + int channels = aud::CHANNELS_STEREO; + double rate = aud::RATE_48000; + float fps = 30.0f; + bool muted = false; + PyObject* mutedo = nullptr; + + self = (Sequence*)type->tp_alloc(type, 0); + if(self != nullptr) + { + static const char* kwlist[] = {"channels", "rate", "fps", "muted", nullptr}; + + if(!PyArg_ParseTupleAndKeywords(args, kwds, "|idfO:Sequence", const_cast<char**>(kwlist), &channels, &rate, &fps, &mutedo)) + { + Py_DECREF(self); + return nullptr; + } + + if(mutedo) + { + if(!PyBool_Check(mutedo)) + { + PyErr_SetString(PyExc_TypeError, "muted is not a boolean!"); + return nullptr; + } + + muted = mutedo == Py_True; + } + + aud::Specs specs; + specs.channels = static_cast<aud::Channels>(channels); + specs.rate = rate; + + try + { + self->sequence = new std::shared_ptr<aud::Sequence>(new aud::Sequence(specs, fps, muted)); + } + catch(Exception& e) + { + Py_DECREF(self); + PyErr_SetString(AUDError, e.what()); + return nullptr; + } + } + + return (PyObject *)self; +} + +PyDoc_STRVAR(M_aud_Sequence_add_doc, + "add()\n\n" + "Adds a new entry to the scene.\n" + ":arg sound: The sound this entry should play.\n" + ":type sound: :class:`Sound`\n" + ":arg begin: The start time.\n" + ":type begin: float\n" + ":arg end: The end time or a negative value if determined by the sound.\n" + ":type end: float\n" + ":arg skip: How much seconds should be skipped at the beginning.\n" + ":type skip: float\n" + ":return: The entry added.\n" + ":rtype: :class:`SequenceEntry`"); + +static PyObject * +Sequence_add(Sequence* self, PyObject* args, PyObject* kwds) +{ + PyObject* object; + float begin; + float end = -1.0f; + float skip = 0.0f; + + static const char* kwlist[] = {"sound", "begin", "end", "skip", nullptr}; + + if(!PyArg_ParseTupleAndKeywords(args, kwds, "Of|ff:add", const_cast<char**>(kwlist), &object, &begin, &end, &skip)) + return nullptr; + + Sound* sound = checkSound(object); + + if(!sound) + return nullptr; + + SequenceEntry* entry; + + entry = (SequenceEntry*)SequenceEntry_empty(); + if(entry != nullptr) + { + try + { + entry->entry = new std::shared_ptr<aud::SequenceEntry>((*reinterpret_cast<std::shared_ptr<aud::Sequence>*>(self->sequence))->add(*reinterpret_cast<std::shared_ptr<ISound>*>(sound->sound), begin, end, skip)); + } + catch(Exception& e) + { + Py_DECREF(entry); + PyErr_SetString(AUDError, e.what()); + return nullptr; + } + } + + return (PyObject *)entry; +} + +PyDoc_STRVAR(M_aud_Sequence_remove_doc, + "reomve()\n\n" + "Adds a new entry to the scene.\n" + ":arg entry: The entry to remove.\n" + ":type entry: :class:`SequenceEntry`\n"); + +static PyObject * +Sequence_remove(Sequence* self, PyObject* args) +{ + PyObject* object; + + if(!PyArg_ParseTuple(args, "O:remove", &object)) + return nullptr; + + SequenceEntry* entry = checkSequenceEntry(object); + + if(!entry) + return nullptr; + + try + { + (*reinterpret_cast<std::shared_ptr<aud::Sequence>*>(self->sequence))->remove(*reinterpret_cast<std::shared_ptr<aud::SequenceEntry>*>(entry->entry)); + Py_RETURN_NONE; + } + catch(Exception& e) + { + Py_DECREF(entry); + PyErr_SetString(AUDError, e.what()); + return nullptr; + } +} + +PyDoc_STRVAR(M_aud_Sequence_setAnimationData_doc, + "setAnimationData()\n\n" + "Writes animation data to a sequence.\n\n" + ":arg type: The type of animation data.\n" + ":type type: int\n" + ":arg frame: The frame this data is for.\n" + ":type frame: int\n" + ":arg data: The data to write.\n" + ":type data: sequence of float\n" + ":arg animated: Whether the attribute is animated.\n" + ":type animated: bool"); + +static PyObject * +Sequence_setAnimationData(Sequence* self, PyObject* args) +{ + int type, frame; + PyObject* py_data; + Py_ssize_t py_data_len; + PyObject* animatedo; + bool animated; + + if(!PyArg_ParseTuple(args, "iiOO:setAnimationData", &type, &frame, &py_data, &animatedo)) + return nullptr; + + if(!PySequence_Check(py_data)) + { + PyErr_SetString(PyExc_TypeError, "Parameter is not a sequence!"); + return nullptr; + } + + py_data_len= PySequence_Size(py_data); + + std::vector<float> data; + data.resize(py_data_len); + + PyObject* py_value; + float value; + + for(Py_ssize_t i = 0; i < py_data_len; i++) + { + py_value = PySequence_GetItem(py_data, i); + value= (float)PyFloat_AsDouble(py_value); + Py_DECREF(py_value); + + if(value == -1.0f && PyErr_Occurred()) { + return nullptr; + } + + data.push_back(value); + } + + if(!PyBool_Check(animatedo)) + { + PyErr_SetString(PyExc_TypeError, "animated is not a boolean!"); + return nullptr; + } + + animated = animatedo == Py_True; + + try + { + AnimateableProperty* prop = (*reinterpret_cast<std::shared_ptr<aud::Sequence>*>(self->sequence))->getAnimProperty(static_cast<AnimateablePropertyType>(type)); + + if(prop->getCount() != py_data_len) + { + PyErr_SetString(PyExc_ValueError, "the amount of floats doesn't fit the animated property"); + return nullptr; + } + + if(animated) + { + if(frame >= 0) + prop->write(&data[0], frame, 1); + } + else + { + prop->write(&data[0]); + } + Py_RETURN_NONE; + } + catch(Exception& e) + { + PyErr_SetString(AUDError, e.what()); + return nullptr; + } +} + +static PyMethodDef Sequence_methods[] = { + {"add", (PyCFunction)Sequence_add, METH_VARARGS | METH_KEYWORDS, + M_aud_Sequence_add_doc + }, + {"remove", (PyCFunction)Sequence_remove, METH_VARARGS, + M_aud_Sequence_remove_doc + }, + {"setAnimationData", (PyCFunction)Sequence_setAnimationData, METH_VARARGS, + M_aud_Sequence_setAnimationData_doc + }, + {nullptr} /* Sentinel */ +}; + +PyDoc_STRVAR(M_aud_Sequence_channels_doc, + "The channel count of the sequence."); + +static PyObject * +Sequence_get_channels(Sequence* self, void* nothing) +{ + try + { + Specs specs = (*reinterpret_cast<std::shared_ptr<aud::Sequence>*>(self->sequence))->getSpecs(); + return Py_BuildValue("i", specs.channels); + } + catch(Exception& e) + { + PyErr_SetString(AUDError, e.what()); + return nullptr; + } +} + +static int +Sequence_set_channels(Sequence* self, PyObject* args, void* nothing) +{ + int channels; + + if(!PyArg_Parse(args, "i:channels", &channels)) + return -1; + + try + { + std::shared_ptr<aud::Sequence> sequence = *reinterpret_cast<std::shared_ptr<aud::Sequence>*>(self->sequence); + Specs specs = sequence->getSpecs(); + specs.channels = static_cast<Channels>(channels); + sequence->setSpecs(specs); + return 0; + } + catch(Exception& e) + { + PyErr_SetString(AUDError, e.what()); + return -1; + } +} + +PyDoc_STRVAR(M_aud_Sequence_distance_model_doc, + "The distance model of the sequence.\n\n" + ".. seealso:: http://connect.creativelabs.com/openal/Documentation/OpenAL%201.1%20Specification.htm#_Toc199835864"); + +static PyObject * +Sequence_get_distance_model(Sequence* self, void* nothing) +{ + try + { + return Py_BuildValue("i", (*reinterpret_cast<std::shared_ptr<aud::Sequence>*>(self->sequence))->getDistanceModel()); + } + catch(Exception& e) + { + PyErr_SetString(AUDError, e.what()); + return nullptr; + } +} + +static int +Sequence_set_distance_model(Sequence* self, PyObject* args, void* nothing) +{ + int distance_model; + + if(!PyArg_Parse(args, "i:distance_model", &distance_model)) + return -1; + + try + { + (*reinterpret_cast<std::shared_ptr<aud::Sequence>*>(self->sequence))->setDistanceModel(static_cast<DistanceModel>(distance_model)); + return 0; + } + catch(Exception& e) + { + PyErr_SetString(AUDError, e.what()); + return -1; + } +} + +PyDoc_STRVAR(M_aud_Sequence_doppler_factor_doc, + "The doppler factor of the sequence.\n" + "This factor is a scaling factor for the velocity vectors in " + "doppler calculation. So a value bigger than 1 will exaggerate " + "the effect as it raises the velocity."); + +static PyObject * +Sequence_get_doppler_factor(Sequence* self, void* nothing) +{ + try + { + return Py_BuildValue("f", (*reinterpret_cast<std::shared_ptr<aud::Sequence>*>(self->sequence))->getDopplerFactor()); + } + catch(Exception& e) + { + PyErr_SetString(AUDError, e.what()); + return nullptr; + } +} + +static int +Sequence_set_doppler_factor(Sequence* self, PyObject* args, void* nothing) +{ + float factor; + + if(!PyArg_Parse(args, "f:doppler_factor", &factor)) + return -1; + + try + { + (*reinterpret_cast<std::shared_ptr<aud::Sequence>*>(self->sequence))->setDopplerFactor(factor); + return 0; + } + catch(Exception& e) + { + PyErr_SetString(AUDError, e.what()); + return -1; + } +} + +PyDoc_STRVAR(M_aud_Sequence_fps_doc, + "The listeners's location in 3D space, a 3D tuple of floats."); + +static PyObject * +Sequence_get_fps(Sequence* self, void* nothing) +{ + try + { + return Py_BuildValue("f", (*reinterpret_cast<std::shared_ptr<aud::Sequence>*>(self->sequence))->getFPS()); + } + catch(Exception& e) + { + PyErr_SetString(AUDError, e.what()); + return nullptr; + } +} + +static int +Sequence_set_fps(Sequence* self, PyObject* args, void* nothing) +{ + float fps; + + if(!PyArg_Parse(args, "f:fps", &fps)) + return -1; + + try + { + (*reinterpret_cast<std::shared_ptr<aud::Sequence>*>(self->sequence))->setFPS(fps); + return 0; + } + catch(Exception& e) + { + PyErr_SetString(AUDError, e.what()); + return -1; + } +} + +PyDoc_STRVAR(M_aud_Sequence_muted_doc, + "Whether the whole sequence is muted.\n"); + +static PyObject * +Sequence_get_muted(Sequence* self, void* nothing) +{ + try + { + std::shared_ptr<aud::Sequence>* sequence = reinterpret_cast<std::shared_ptr<aud::Sequence>*>(self->sequence); + return PyBool_FromLong((long)(*sequence)->isMuted()); + } + catch(Exception& e) + { + PyErr_SetString(AUDError, e.what()); + return nullptr; + } +} + +static int +Sequence_set_muted(Sequence* self, PyObject* args, void* nothing) +{ + if(!PyBool_Check(args)) + { + PyErr_SetString(PyExc_TypeError, "muted is not a boolean!"); + return -1; + } + + bool muted = args == Py_True; + + try + { + std::shared_ptr<aud::Sequence>* sequence = reinterpret_cast<std::shared_ptr<aud::Sequence>*>(self->sequence); + (*sequence)->mute(muted); + return 0; + } + catch(Exception& e) + { + PyErr_SetString(AUDError, e.what()); + } + + return -1; +} + +PyDoc_STRVAR(M_aud_Sequence_rate_doc, + "The sampling rate of the sequence in Hz."); + +static PyObject * +Sequence_get_rate(Sequence* self, void* nothing) +{ + try + { + Specs specs = (*reinterpret_cast<std::shared_ptr<aud::Sequence>*>(self->sequence))->getSpecs(); + return Py_BuildValue("d", specs.rate); + } + catch(Exception& e) + { + PyErr_SetString(AUDError, e.what()); + return nullptr; + } +} + +static int +Sequence_set_rate(Sequence* self, PyObject* args, void* nothing) +{ + double rate; + + if(!PyArg_Parse(args, "d:rate", &rate)) + return -1; + + try + { + std::shared_ptr<aud::Sequence> sequence = *reinterpret_cast<std::shared_ptr<aud::Sequence>*>(self->sequence); + Specs specs = sequence->getSpecs(); + specs.rate = rate; + sequence->setSpecs(specs); + return 0; + } + catch(Exception& e) + { + PyErr_SetString(AUDError, e.what()); + return -1; + } +} + +PyDoc_STRVAR(M_aud_Sequence_speed_of_sound_doc, + "The speed of sound of the sequence.\n" + "The speed of sound in air is typically 343.3 m/s."); + +static PyObject * +Sequence_get_speed_of_sound(Sequence* self, void* nothing) +{ + try + { + return Py_BuildValue("f", (*reinterpret_cast<std::shared_ptr<aud::Sequence>*>(self->sequence))->getSpeedOfSound()); + } + catch(Exception& e) + { + PyErr_SetString(AUDError, e.what()); + return nullptr; + } +} + +static int +Sequence_set_speed_of_sound(Sequence* self, PyObject* args, void* nothing) +{ + float speed; + + if(!PyArg_Parse(args, "f:speed_of_sound", &speed)) + return -1; + + try + { + (*reinterpret_cast<std::shared_ptr<aud::Sequence>*>(self->sequence))->setSpeedOfSound(speed); + return 0; + } + catch(Exception& e) + { + PyErr_SetString(AUDError, e.what()); + return -1; + } +} + +static PyGetSetDef Sequence_properties[] = { + {(char*)"channels", (getter)Sequence_get_channels, (setter)Sequence_set_channels, + M_aud_Sequence_channels_doc, nullptr }, + {(char*)"distance_model", (getter)Sequence_get_distance_model, (setter)Sequence_set_distance_model, + M_aud_Sequence_distance_model_doc, nullptr }, + {(char*)"doppler_factor", (getter)Sequence_get_doppler_factor, (setter)Sequence_set_doppler_factor, + M_aud_Sequence_doppler_factor_doc, nullptr }, + {(char*)"fps", (getter)Sequence_get_fps, (setter)Sequence_set_fps, + M_aud_Sequence_fps_doc, nullptr }, + {(char*)"muted", (getter)Sequence_get_muted, (setter)Sequence_set_muted, + M_aud_Sequence_muted_doc, nullptr }, + {(char*)"rate", (getter)Sequence_get_rate, (setter)Sequence_set_rate, + M_aud_Sequence_rate_doc, nullptr }, + {(char*)"speed_of_sound", (getter)Sequence_get_speed_of_sound, (setter)Sequence_set_speed_of_sound, + M_aud_Sequence_speed_of_sound_doc, nullptr }, + {nullptr} /* Sentinel */ +}; + +PyDoc_STRVAR(M_aud_Sequence_doc, + "This sound represents sequenced entries to play a sound scene."); + +extern PyTypeObject SoundType; + +static PyTypeObject SequenceType = { + PyVarObject_HEAD_INIT(nullptr, 0) + "aud.Sequence", /* tp_name */ + sizeof(Sequence), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)Sequence_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_Sequence_doc, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + Sequence_methods, /* tp_methods */ + 0, /* tp_members */ + Sequence_properties, /* tp_getset */ + &SoundType, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + Sequence_new, /* tp_new */ +}; + +AUD_API PyObject* Sequence_empty() +{ + return SequenceType.tp_alloc(&SequenceType, 0); +} + + +AUD_API Sequence* checkSequence(PyObject* sequence) +{ + if(!PyObject_TypeCheck(sequence, &SequenceType)) + { + PyErr_SetString(PyExc_TypeError, "Object is not of type Sequence!"); + return nullptr; + } + + return (Sequence*)sequence; +} + + +bool initializeSequence() +{ + return PyType_Ready(&SequenceType) >= 0; +} + + +void addSequenceToModule(PyObject* module) +{ + Py_INCREF(&SequenceType); + PyModule_AddObject(module, "Sequence", (PyObject *)&SequenceType); +} |