1 /*******************************************************************************
2  * Copyright 2009-2016 Jörg Müller
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  ******************************************************************************/
16 
17 #include "PySequenceEntry.h"
18 
19 #include "PySound.h"
20 
21 #include "Exception.h"
22 #include "sequence/AnimateableProperty.h"
23 #include "sequence/SequenceEntry.h"
24 
25 #include <structmember.h>
26 #include <vector>
27 
28 using aud::Exception;
29 using aud::AnimateableProperty;
30 using aud::AnimateablePropertyType;
31 using aud::ISound;
32 
33 extern PyObject* AUDError;
34 
35 // ====================================================================
36 
37 static void
SequenceEntry_dealloc(SequenceEntry * self)38 SequenceEntry_dealloc(SequenceEntry* self)
39 {
40 	if(self->entry)
41 		delete reinterpret_cast<std::shared_ptr<aud::SequenceEntry>*>(self->entry);
42 	Py_TYPE(self)->tp_free((PyObject *)self);
43 }
44 
45 PyDoc_STRVAR(M_aud_SequenceEntry_move_doc,
46 			 ".. classmethod:: move()\n\n"
47 			 "   Moves the entry.\n\n"
48 			 "   :arg begin: The new start time.\n"
49 			 "   :type begin: double\n"
50 			 "   :arg end: The new end time or a negative value if unknown.\n"
51 			 "   :type end: double\n"
52 			 "   :arg skip: How many seconds to skip at the beginning.\n"
53 			 "   :type skip: double\n");
54 
55 static PyObject *
SequenceEntry_move(SequenceEntry * self,PyObject * args)56 SequenceEntry_move(SequenceEntry* self, PyObject* args)
57 {
58 	double begin, end, skip;
59 
60 	if(!PyArg_ParseTuple(args, "ddd:move", &begin, &end, &skip))
61 		return nullptr;
62 
63 	try
64 	{
65 		(*reinterpret_cast<std::shared_ptr<aud::SequenceEntry>*>(self->entry))->move(begin, end, skip);
66 		Py_RETURN_NONE;
67 	}
68 	catch(Exception& e)
69 	{
70 		PyErr_SetString(AUDError, e.what());
71 		return nullptr;
72 	}
73 }
74 
75 PyDoc_STRVAR(M_aud_SequenceEntry_setAnimationData_doc,
76 			 ".. classmethod:: setAnimationData()\n\n"
77 			 "   Writes animation data to a sequenced entry.\n\n"
78 			 "   :arg type: The type of animation data.\n"
79 			 "   :type type: int\n"
80 			 "   :arg frame: The frame this data is for.\n"
81 			 "   :type frame: int\n"
82 			 "   :arg data: The data to write.\n"
83 			 "   :type data: sequence of float\n"
84 			 "   :arg animated: Whether the attribute is animated.\n"
85 			 "   :type animated: bool");
86 
87 static PyObject *
SequenceEntry_setAnimationData(SequenceEntry * self,PyObject * args)88 SequenceEntry_setAnimationData(SequenceEntry* self, PyObject* args)
89 {
90 	int type, frame;
91 	PyObject* py_data;
92 	Py_ssize_t py_data_len;
93 	PyObject* animatedo;
94 	bool animated;
95 
96 	if(!PyArg_ParseTuple(args, "iiOO:setAnimationData", &type, &frame, &py_data, &animatedo))
97 		return nullptr;
98 
99 	if(!PySequence_Check(py_data))
100 	{
101 		PyErr_SetString(PyExc_TypeError, "Parameter is not a sequence!");
102 		return nullptr;
103 	}
104 
105 	py_data_len= PySequence_Size(py_data);
106 
107 	std::vector<float> data;
108 	data.resize(py_data_len);
109 
110 	PyObject* py_value;
111 	float value;
112 
113 	for(Py_ssize_t i = 0; i < py_data_len; i++)
114 	{
115 		py_value = PySequence_GetItem(py_data, i);
116 		value= (float)PyFloat_AsDouble(py_value);
117 		Py_DECREF(py_value);
118 
119 		if(value == -1.0f && PyErr_Occurred()) {
120 			return nullptr;
121 		}
122 
123 		data.push_back(value);
124 	}
125 
126 	if(!PyBool_Check(animatedo))
127 	{
128 		PyErr_SetString(PyExc_TypeError, "animated is not a boolean!");
129 		return nullptr;
130 	}
131 
132 	animated = animatedo == Py_True;
133 
134 	try
135 	{
136 		AnimateableProperty* prop = (*reinterpret_cast<std::shared_ptr<aud::SequenceEntry>*>(self->entry))->getAnimProperty(static_cast<AnimateablePropertyType>(type));
137 
138 		if(prop->getCount() != py_data_len)
139 		{
140 			PyErr_SetString(PyExc_ValueError, "the amount of floats doesn't fit the animated property");
141 			return nullptr;
142 		}
143 
144 		if(animated)
145 		{
146 			if(frame >= 0)
147 				prop->write(&data[0], frame, 1);
148 		}
149 		else
150 		{
151 			prop->write(&data[0]);
152 		}
153 		Py_RETURN_NONE;
154 	}
155 	catch(Exception& e)
156 	{
157 		PyErr_SetString(AUDError, e.what());
158 		return nullptr;
159 	}
160 }
161 
162 static PyMethodDef SequenceEntry_methods[] = {
163 	{"move", (PyCFunction)SequenceEntry_move, METH_VARARGS,
164 	 M_aud_SequenceEntry_move_doc
165 	},
166 	{"setAnimationData", (PyCFunction)SequenceEntry_setAnimationData, METH_VARARGS,
167 	 M_aud_SequenceEntry_setAnimationData_doc
168 	},
169 	{nullptr}  /* Sentinel */
170 };
171 
172 PyDoc_STRVAR(M_aud_SequenceEntry_attenuation_doc,
173 			 "This factor is used for distance based attenuation of the "
174 			 "source.\n\n"
175 			 ".. seealso:: :attr:`Device.distance_model`");
176 
177 static PyObject *
SequenceEntry_get_attenuation(SequenceEntry * self,void * nothing)178 SequenceEntry_get_attenuation(SequenceEntry* self, void* nothing)
179 {
180 	try
181 	{
182 		std::shared_ptr<aud::SequenceEntry>* entry = reinterpret_cast<std::shared_ptr<aud::SequenceEntry>*>(self->entry);
183 		return Py_BuildValue("f", (*entry)->getAttenuation());
184 	}
185 	catch(Exception& e)
186 	{
187 		PyErr_SetString(AUDError, e.what());
188 		return nullptr;
189 	}
190 }
191 
192 static int
SequenceEntry_set_attenuation(SequenceEntry * self,PyObject * args,void * nothing)193 SequenceEntry_set_attenuation(SequenceEntry* self, PyObject* args, void* nothing)
194 {
195 	float factor;
196 
197 	if(!PyArg_Parse(args, "f:attenuation", &factor))
198 		return -1;
199 
200 	try
201 	{
202 		std::shared_ptr<aud::SequenceEntry>* entry = reinterpret_cast<std::shared_ptr<aud::SequenceEntry>*>(self->entry);
203 		(*entry)->setAttenuation(factor);
204 		return 0;
205 	}
206 	catch(Exception& e)
207 	{
208 		PyErr_SetString(AUDError, e.what());
209 	}
210 
211 	return -1;
212 }
213 
214 PyDoc_STRVAR(M_aud_SequenceEntry_cone_angle_inner_doc,
215 			 "The opening angle of the inner cone of the source. If the cone "
216 			 "values of a source are set there are two (audible) cones with "
217 			 "the apex at the :attr:`location` of the source and with infinite "
218 			 "height, heading in the direction of the source's "
219 			 ":attr:`orientation`.\n"
220 			 "In the inner cone the volume is normal. Outside the outer cone "
221 			 "the volume will be :attr:`cone_volume_outer` and in the area "
222 			 "between the volume will be interpolated linearly.");
223 
224 static PyObject *
SequenceEntry_get_cone_angle_inner(SequenceEntry * self,void * nothing)225 SequenceEntry_get_cone_angle_inner(SequenceEntry* self, void* nothing)
226 {
227 	try
228 	{
229 		std::shared_ptr<aud::SequenceEntry>* entry = reinterpret_cast<std::shared_ptr<aud::SequenceEntry>*>(self->entry);
230 		return Py_BuildValue("f", (*entry)->getConeAngleInner());
231 	}
232 	catch(Exception& e)
233 	{
234 		PyErr_SetString(AUDError, e.what());
235 		return nullptr;
236 	}
237 }
238 
239 static int
SequenceEntry_set_cone_angle_inner(SequenceEntry * self,PyObject * args,void * nothing)240 SequenceEntry_set_cone_angle_inner(SequenceEntry* self, PyObject* args, void* nothing)
241 {
242 	float angle;
243 
244 	if(!PyArg_Parse(args, "f:cone_angle_inner", &angle))
245 		return -1;
246 
247 	try
248 	{
249 		std::shared_ptr<aud::SequenceEntry>* entry = reinterpret_cast<std::shared_ptr<aud::SequenceEntry>*>(self->entry);
250 		(*entry)->setConeAngleInner(angle);
251 		return 0;
252 	}
253 	catch(Exception& e)
254 	{
255 		PyErr_SetString(AUDError, e.what());
256 	}
257 
258 	return -1;
259 }
260 
261 PyDoc_STRVAR(M_aud_SequenceEntry_cone_angle_outer_doc,
262 			 "The opening angle of the outer cone of the source.\n\n"
263 			 ".. seealso:: :attr:`cone_angle_inner`");
264 
265 static PyObject *
SequenceEntry_get_cone_angle_outer(SequenceEntry * self,void * nothing)266 SequenceEntry_get_cone_angle_outer(SequenceEntry* self, void* nothing)
267 {
268 	try
269 	{
270 		std::shared_ptr<aud::SequenceEntry>* entry = reinterpret_cast<std::shared_ptr<aud::SequenceEntry>*>(self->entry);
271 		return Py_BuildValue("f", (*entry)->getConeAngleOuter());
272 	}
273 	catch(Exception& e)
274 	{
275 		PyErr_SetString(AUDError, e.what());
276 		return nullptr;
277 	}
278 }
279 
280 static int
SequenceEntry_set_cone_angle_outer(SequenceEntry * self,PyObject * args,void * nothing)281 SequenceEntry_set_cone_angle_outer(SequenceEntry* self, PyObject* args, void* nothing)
282 {
283 	float angle;
284 
285 	if(!PyArg_Parse(args, "f:cone_angle_outer", &angle))
286 		return -1;
287 
288 	try
289 	{
290 		std::shared_ptr<aud::SequenceEntry>* entry = reinterpret_cast<std::shared_ptr<aud::SequenceEntry>*>(self->entry);
291 		(*entry)->setConeAngleOuter(angle);
292 		return 0;
293 	}
294 	catch(Exception& e)
295 	{
296 		PyErr_SetString(AUDError, e.what());
297 	}
298 
299 	return -1;
300 }
301 
302 PyDoc_STRVAR(M_aud_SequenceEntry_cone_volume_outer_doc,
303 			 "The volume outside the outer cone of the source.\n\n"
304 			 ".. seealso:: :attr:`cone_angle_inner`");
305 
306 static PyObject *
SequenceEntry_get_cone_volume_outer(SequenceEntry * self,void * nothing)307 SequenceEntry_get_cone_volume_outer(SequenceEntry* self, void* nothing)
308 {
309 	try
310 	{
311 		std::shared_ptr<aud::SequenceEntry>* entry = reinterpret_cast<std::shared_ptr<aud::SequenceEntry>*>(self->entry);
312 		return Py_BuildValue("f", (*entry)->getConeVolumeOuter());
313 	}
314 	catch(Exception& e)
315 	{
316 		PyErr_SetString(AUDError, e.what());
317 		return nullptr;
318 	}
319 }
320 
321 static int
SequenceEntry_set_cone_volume_outer(SequenceEntry * self,PyObject * args,void * nothing)322 SequenceEntry_set_cone_volume_outer(SequenceEntry* self, PyObject* args, void* nothing)
323 {
324 	float volume;
325 
326 	if(!PyArg_Parse(args, "f:cone_volume_outer", &volume))
327 		return -1;
328 
329 	try
330 	{
331 		std::shared_ptr<aud::SequenceEntry>* entry = reinterpret_cast<std::shared_ptr<aud::SequenceEntry>*>(self->entry);
332 		(*entry)->setConeVolumeOuter(volume);
333 		return 0;
334 	}
335 	catch(Exception& e)
336 	{
337 		PyErr_SetString(AUDError, e.what());
338 	}
339 
340 	return -1;
341 }
342 
343 PyDoc_STRVAR(M_aud_SequenceEntry_distance_maximum_doc,
344 			 "The maximum distance of the source.\n"
345 			 "If the listener is further away the source volume will be 0.\n\n"
346 			 ".. seealso:: :attr:`Device.distance_model`");
347 
348 static PyObject *
SequenceEntry_get_distance_maximum(SequenceEntry * self,void * nothing)349 SequenceEntry_get_distance_maximum(SequenceEntry* self, void* nothing)
350 {
351 	try
352 	{
353 		std::shared_ptr<aud::SequenceEntry>* entry = reinterpret_cast<std::shared_ptr<aud::SequenceEntry>*>(self->entry);
354 		return Py_BuildValue("f", (*entry)->getDistanceMaximum());
355 	}
356 	catch(Exception& e)
357 	{
358 		PyErr_SetString(AUDError, e.what());
359 		return nullptr;
360 	}
361 }
362 
363 static int
SequenceEntry_set_distance_maximum(SequenceEntry * self,PyObject * args,void * nothing)364 SequenceEntry_set_distance_maximum(SequenceEntry* self, PyObject* args, void* nothing)
365 {
366 	float distance;
367 
368 	if(!PyArg_Parse(args, "f:distance_maximum", &distance))
369 		return -1;
370 
371 	try
372 	{
373 		std::shared_ptr<aud::SequenceEntry>* entry = reinterpret_cast<std::shared_ptr<aud::SequenceEntry>*>(self->entry);
374 		(*entry)->setDistanceMaximum(distance);
375 		return 0;
376 	}
377 	catch(Exception& e)
378 	{
379 		PyErr_SetString(AUDError, e.what());
380 	}
381 
382 	return -1;
383 }
384 
385 PyDoc_STRVAR(M_aud_SequenceEntry_distance_reference_doc,
386 			 "The reference distance of the source.\n"
387 			 "At this distance the volume will be exactly :attr:`volume`.\n\n"
388 			 ".. seealso:: :attr:`Device.distance_model`");
389 
390 static PyObject *
SequenceEntry_get_distance_reference(SequenceEntry * self,void * nothing)391 SequenceEntry_get_distance_reference(SequenceEntry* self, void* nothing)
392 {
393 	try
394 	{
395 		std::shared_ptr<aud::SequenceEntry>* entry = reinterpret_cast<std::shared_ptr<aud::SequenceEntry>*>(self->entry);
396 		return Py_BuildValue("f", (*entry)->getDistanceReference());
397 	}
398 	catch(Exception& e)
399 	{
400 		PyErr_SetString(AUDError, e.what());
401 		return nullptr;
402 	}
403 }
404 
405 static int
SequenceEntry_set_distance_reference(SequenceEntry * self,PyObject * args,void * nothing)406 SequenceEntry_set_distance_reference(SequenceEntry* self, PyObject* args, void* nothing)
407 {
408 	float distance;
409 
410 	if(!PyArg_Parse(args, "f:distance_reference", &distance))
411 		return -1;
412 
413 	try
414 	{
415 		std::shared_ptr<aud::SequenceEntry>* entry = reinterpret_cast<std::shared_ptr<aud::SequenceEntry>*>(self->entry);
416 		(*entry)->setDistanceReference(distance);
417 		return 0;
418 	}
419 	catch(Exception& e)
420 	{
421 		PyErr_SetString(AUDError, e.what());
422 	}
423 
424 	return -1;
425 }
426 
427 PyDoc_STRVAR(M_aud_SequenceEntry_muted_doc,
428 			 "Whether the entry is muted.\n");
429 
430 static PyObject *
SequenceEntry_get_muted(SequenceEntry * self,void * nothing)431 SequenceEntry_get_muted(SequenceEntry* self, void* nothing)
432 {
433 	try
434 	{
435 		std::shared_ptr<aud::SequenceEntry>* entry = reinterpret_cast<std::shared_ptr<aud::SequenceEntry>*>(self->entry);
436 		return PyBool_FromLong((long)(*entry)->isMuted());
437 	}
438 	catch(Exception& e)
439 	{
440 		PyErr_SetString(AUDError, e.what());
441 		return nullptr;
442 	}
443 }
444 
445 static int
SequenceEntry_set_muted(SequenceEntry * self,PyObject * args,void * nothing)446 SequenceEntry_set_muted(SequenceEntry* self, PyObject* args, void* nothing)
447 {
448 	if(!PyBool_Check(args))
449 	{
450 		PyErr_SetString(PyExc_TypeError, "muted is not a boolean!");
451 		return -1;
452 	}
453 
454 	bool muted = args == Py_True;
455 
456 	try
457 	{
458 		std::shared_ptr<aud::SequenceEntry>* entry = reinterpret_cast<std::shared_ptr<aud::SequenceEntry>*>(self->entry);
459 		(*entry)->mute(muted);
460 		return 0;
461 	}
462 	catch(Exception& e)
463 	{
464 		PyErr_SetString(AUDError, e.what());
465 	}
466 
467 	return -1;
468 }
469 
470 PyDoc_STRVAR(M_aud_SequenceEntry_relative_doc,
471 			 "Whether the source's location, velocity and orientation is relative or absolute to the listener.");
472 
473 static PyObject *
SequenceEntry_get_relative(SequenceEntry * self,void * nothing)474 SequenceEntry_get_relative(SequenceEntry* self, void* nothing)
475 {
476 	try
477 	{
478 		std::shared_ptr<aud::SequenceEntry>* entry = reinterpret_cast<std::shared_ptr<aud::SequenceEntry>*>(self->entry);
479 		return PyBool_FromLong((long)(*entry)->isRelative());
480 	}
481 	catch(Exception& e)
482 	{
483 		PyErr_SetString(AUDError, e.what());
484 	}
485 
486 	return nullptr;
487 }
488 
489 static int
SequenceEntry_set_relative(SequenceEntry * self,PyObject * args,void * nothing)490 SequenceEntry_set_relative(SequenceEntry* self, PyObject* args, void* nothing)
491 {
492 	if(!PyBool_Check(args))
493 	{
494 		PyErr_SetString(PyExc_TypeError, "Value is not a boolean!");
495 		return -1;
496 	}
497 
498 	bool relative = (args == Py_True);
499 
500 	try
501 	{
502 		std::shared_ptr<aud::SequenceEntry>* entry = reinterpret_cast<std::shared_ptr<aud::SequenceEntry>*>(self->entry);
503 		(*entry)->setRelative(relative);
504 		return 0;
505 	}
506 	catch(Exception& e)
507 	{
508 		PyErr_SetString(AUDError, e.what());
509 	}
510 
511 	return -1;
512 }
513 
514 PyDoc_STRVAR(M_aud_SequenceEntry_sound_doc,
515 			 "The sound the entry is representing and will be played in the sequence.");
516 
517 static PyObject *
SequenceEntry_get_sound(SequenceEntry * self,void * nothing)518 SequenceEntry_get_sound(SequenceEntry* self, void* nothing)
519 {
520 	try
521 	{
522 		std::shared_ptr<aud::SequenceEntry>* entry = reinterpret_cast<std::shared_ptr<aud::SequenceEntry>*>(self->entry);
523 		Sound* object = (Sound*) Sound_empty();
524 		if(object)
525 		{
526 			object->sound = new std::shared_ptr<ISound>((*entry)->getSound());
527 			return (PyObject *) object;
528 		}
529 	}
530 	catch(Exception& e)
531 	{
532 		PyErr_SetString(AUDError, e.what());
533 	}
534 
535 	return nullptr;
536 }
537 
538 static int
SequenceEntry_set_sound(SequenceEntry * self,PyObject * args,void * nothing)539 SequenceEntry_set_sound(SequenceEntry* self, PyObject* args, void* nothing)
540 {
541 	Sound* sound = checkSound(args);
542 
543 	if(!sound)
544 		return -1;
545 
546 	try
547 	{
548 		std::shared_ptr<aud::SequenceEntry>* entry = reinterpret_cast<std::shared_ptr<aud::SequenceEntry>*>(self->entry);
549 		(*entry)->setSound(*reinterpret_cast<std::shared_ptr<ISound>*>(sound->sound));
550 		return 0;
551 	}
552 	catch(Exception& e)
553 	{
554 		PyErr_SetString(AUDError, e.what());
555 	}
556 
557 	return -1;
558 }
559 
560 PyDoc_STRVAR(M_aud_SequenceEntry_volume_maximum_doc,
561 			 "The maximum volume of the source.\n\n"
562 			 ".. seealso:: :attr:`Device.distance_model`");
563 
564 static PyObject *
SequenceEntry_get_volume_maximum(SequenceEntry * self,void * nothing)565 SequenceEntry_get_volume_maximum(SequenceEntry* self, void* nothing)
566 {
567 	try
568 	{
569 		std::shared_ptr<aud::SequenceEntry>* entry = reinterpret_cast<std::shared_ptr<aud::SequenceEntry>*>(self->entry);
570 		return Py_BuildValue("f", (*entry)->getVolumeMaximum());
571 	}
572 	catch(Exception& e)
573 	{
574 		PyErr_SetString(AUDError, e.what());
575 		return nullptr;
576 	}
577 }
578 
579 static int
SequenceEntry_set_volume_maximum(SequenceEntry * self,PyObject * args,void * nothing)580 SequenceEntry_set_volume_maximum(SequenceEntry* self, PyObject* args, void* nothing)
581 {
582 	float volume;
583 
584 	if(!PyArg_Parse(args, "f:volume_maximum", &volume))
585 		return -1;
586 
587 	try
588 	{
589 		std::shared_ptr<aud::SequenceEntry>* entry = reinterpret_cast<std::shared_ptr<aud::SequenceEntry>*>(self->entry);
590 		(*entry)->setVolumeMaximum(volume);
591 		return 0;
592 	}
593 	catch(Exception& e)
594 	{
595 		PyErr_SetString(AUDError, e.what());
596 	}
597 
598 	return -1;
599 }
600 
601 PyDoc_STRVAR(M_aud_SequenceEntry_volume_minimum_doc,
602 			 "The minimum volume of the source.\n\n"
603 			 ".. seealso:: :attr:`Device.distance_model`");
604 
605 static PyObject *
SequenceEntry_get_volume_minimum(SequenceEntry * self,void * nothing)606 SequenceEntry_get_volume_minimum(SequenceEntry* self, void* nothing)
607 {
608 	try
609 	{
610 		std::shared_ptr<aud::SequenceEntry>* entry = reinterpret_cast<std::shared_ptr<aud::SequenceEntry>*>(self->entry);
611 		return Py_BuildValue("f", (*entry)->getVolumeMinimum());
612 	}
613 	catch(Exception& e)
614 	{
615 		PyErr_SetString(AUDError, e.what());
616 		return nullptr;
617 	}
618 }
619 
620 static int
SequenceEntry_set_volume_minimum(SequenceEntry * self,PyObject * args,void * nothing)621 SequenceEntry_set_volume_minimum(SequenceEntry* self, PyObject* args, void* nothing)
622 {
623 	float volume;
624 
625 	if(!PyArg_Parse(args, "f:volume_minimum", &volume))
626 		return -1;
627 
628 	try
629 	{
630 		std::shared_ptr<aud::SequenceEntry>* entry = reinterpret_cast<std::shared_ptr<aud::SequenceEntry>*>(self->entry);
631 		(*entry)->setVolumeMinimum(volume);
632 		return 0;
633 	}
634 	catch(Exception& e)
635 	{
636 		PyErr_SetString(AUDError, e.what());
637 	}
638 
639 	return -1;
640 }
641 
642 static PyGetSetDef SequenceEntry_properties[] = {
643 	{(char*)"attenuation", (getter)SequenceEntry_get_attenuation, (setter)SequenceEntry_set_attenuation,
644 	 M_aud_SequenceEntry_attenuation_doc, nullptr },
645 	{(char*)"cone_angle_inner", (getter)SequenceEntry_get_cone_angle_inner, (setter)SequenceEntry_set_cone_angle_inner,
646 	 M_aud_SequenceEntry_cone_angle_inner_doc, nullptr },
647 	{(char*)"cone_angle_outer", (getter)SequenceEntry_get_cone_angle_outer, (setter)SequenceEntry_set_cone_angle_outer,
648 	 M_aud_SequenceEntry_cone_angle_outer_doc, nullptr },
649 	{(char*)"cone_volume_outer", (getter)SequenceEntry_get_cone_volume_outer, (setter)SequenceEntry_set_cone_volume_outer,
650 	 M_aud_SequenceEntry_cone_volume_outer_doc, nullptr },
651 	{(char*)"distance_maximum", (getter)SequenceEntry_get_distance_maximum, (setter)SequenceEntry_set_distance_maximum,
652 	 M_aud_SequenceEntry_distance_maximum_doc, nullptr },
653 	{(char*)"distance_reference", (getter)SequenceEntry_get_distance_reference, (setter)SequenceEntry_set_distance_reference,
654 	 M_aud_SequenceEntry_distance_reference_doc, nullptr },
655 	{(char*)"muted", (getter)SequenceEntry_get_muted, (setter)SequenceEntry_set_muted,
656 	 M_aud_SequenceEntry_muted_doc, nullptr },
657 	{(char*)"relative", (getter)SequenceEntry_get_relative, (setter)SequenceEntry_set_relative,
658 	 M_aud_SequenceEntry_relative_doc, nullptr },
659 	{(char*)"sound", (getter)SequenceEntry_get_sound, (setter)SequenceEntry_set_sound,
660 	 M_aud_SequenceEntry_sound_doc, nullptr },
661 	{(char*)"volume_maximum", (getter)SequenceEntry_get_volume_maximum, (setter)SequenceEntry_set_volume_maximum,
662 	 M_aud_SequenceEntry_volume_maximum_doc, nullptr },
663 	{(char*)"volume_minimum", (getter)SequenceEntry_get_volume_minimum, (setter)SequenceEntry_set_volume_minimum,
664 	 M_aud_SequenceEntry_volume_minimum_doc, nullptr },
665 	{nullptr}  /* Sentinel */
666 };
667 
668 PyDoc_STRVAR(M_aud_SequenceEntry_doc,
669 			 "SequenceEntry objects represent an entry of a sequenced sound.");
670 
671 static PyTypeObject SequenceEntryType = {
672 	PyVarObject_HEAD_INIT(nullptr, 0)
673 	"aud.SequenceEntry",               /* tp_name */
674 	sizeof(SequenceEntry),             /* tp_basicsize */
675 	0,                                 /* tp_itemsize */
676 	(destructor)SequenceEntry_dealloc, /* tp_dealloc */
677 	0,                                 /* tp_print */
678 	0,                                 /* tp_getattr */
679 	0,                                 /* tp_setattr */
680 	0,                                 /* tp_reserved */
681 	0,                                 /* tp_repr */
682 	0,                                 /* tp_as_number */
683 	0,                                 /* tp_as_sequence */
684 	0,                                 /* tp_as_mapping */
685 	0,                                 /* tp_hash  */
686 	0,                                 /* tp_call */
687 	0,                                 /* tp_str */
688 	0,                                 /* tp_getattro */
689 	0,                                 /* tp_setattro */
690 	0,                                 /* tp_as_buffer */
691 	Py_TPFLAGS_DEFAULT,                /* tp_flags */
692 	M_aud_SequenceEntry_doc,           /* tp_doc */
693 	0,                                 /* tp_traverse */
694 	0,                                 /* tp_clear */
695 	0,                                 /* tp_richcompare */
696 	0,                                 /* tp_weaklistoffset */
697 	0,                                 /* tp_iter */
698 	0,                                 /* tp_iternext */
699 	SequenceEntry_methods,             /* tp_methods */
700 	0,                                 /* tp_members */
701 	SequenceEntry_properties,          /* tp_getset */
702 	0,                                 /* tp_base */
703 	0,                                 /* tp_dict */
704 	0,                                 /* tp_descr_get */
705 	0,                                 /* tp_descr_set */
706 	0,                                 /* tp_dictoffset */
707 	0,                                 /* tp_init */
708 	0,                                 /* tp_alloc */
709 	0,                                 /* tp_new */
710 };
711 
SequenceEntry_empty()712 AUD_API PyObject* SequenceEntry_empty()
713 {
714 	return SequenceEntryType.tp_alloc(&SequenceEntryType, 0);
715 }
716 
717 
checkSequenceEntry(PyObject * entry)718 AUD_API SequenceEntry* checkSequenceEntry(PyObject* entry)
719 {
720 	if(!PyObject_TypeCheck(entry, &SequenceEntryType))
721 	{
722 		PyErr_SetString(PyExc_TypeError, "Object is not of type SequenceEntry!");
723 		return nullptr;
724 	}
725 
726 	return (SequenceEntry*)entry;
727 }
728 
729 
initializeSequenceEntry()730 bool initializeSequenceEntry()
731 {
732 	return PyType_Ready(&SequenceEntryType) >= 0;
733 }
734 
735 
addSequenceEntryToModule(PyObject * module)736 void addSequenceEntryToModule(PyObject* module)
737 {
738 	Py_INCREF(&SequenceEntryType);
739 	PyModule_AddObject(module, "SequenceEntry", (PyObject *)&SequenceEntryType);
740 }
741