1 /*******************************************************************************
2 * Copyright 2015-2016 Juan Francisco Crespo Galán
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 "PyDynamicMusic.h"
18 #include "PySound.h"
19 #include "PyHandle.h"
20 #include "PyDevice.h"
21
22 #include "Exception.h"
23 #include "fx/DynamicMusic.h"
24
25 extern PyObject* AUDError;
26
27 static PyObject *
DynamicMusic_new(PyTypeObject * type,PyObject * args,PyObject * kwds)28 DynamicMusic_new(PyTypeObject* type, PyObject* args, PyObject* kwds)
29 {
30 DynamicMusicP* self = (DynamicMusicP*)type->tp_alloc(type, 0);
31
32 if(self != nullptr)
33 {
34 PyObject* object;
35 if(!PyArg_ParseTuple(args, "O:device", &object))
36 return nullptr;
37 Device* device = checkDevice(object);
38
39 try
40 {
41 self->dynamicMusic = new std::shared_ptr<aud::DynamicMusic>(new aud::DynamicMusic(*reinterpret_cast<std::shared_ptr<aud::IDevice>*>(device->device)));
42 }
43 catch(aud::Exception& e)
44 {
45 Py_DECREF(self);
46 PyErr_SetString(AUDError, e.what());
47 return nullptr;
48 }
49 }
50
51 return (PyObject *)self;
52 }
53
54 static void
DynamicMusic_dealloc(DynamicMusicP * self)55 DynamicMusic_dealloc(DynamicMusicP* self)
56 {
57 if(self->dynamicMusic)
58 delete reinterpret_cast<std::shared_ptr<aud::DynamicMusic>*>(self->dynamicMusic);
59 Py_TYPE(self)->tp_free((PyObject *)self);
60 }
61
62 PyDoc_STRVAR(M_aud_DynamicMusic_addScene_doc,
63 ".. classmethod:: addScene(scene)\n\n"
64 " Adds a new scene.\n\n"
65 " :arg scene: The scene sound.\n"
66 " :type scene: :class:`Sound`\n"
67 " :return: The new scene id.\n"
68 " :rtype: int");
69
70 static PyObject *
DynamicMusic_addScene(DynamicMusicP * self,PyObject * args)71 DynamicMusic_addScene(DynamicMusicP* self, PyObject* args)
72 {
73 PyObject* object;
74 if(!PyArg_Parse(args, "O:sound", &object))
75 return nullptr;
76
77 Sound* sound = checkSound(object);
78 if(!sound)
79 return nullptr;
80
81 try
82 {
83 return Py_BuildValue("i", (*reinterpret_cast<std::shared_ptr<aud::DynamicMusic>*>(self->dynamicMusic))->addScene(*reinterpret_cast<std::shared_ptr<aud::ISound>*>(sound->sound)));
84 }
85 catch(aud::Exception& e)
86 {
87 PyErr_SetString(AUDError, e.what());
88 return nullptr;
89 }
90 }
91
92 PyDoc_STRVAR(M_aud_DynamicMusic_addTransition_doc,
93 ".. classmethod:: addTransition(ini, end, transition)\n\n"
94 " Adds a new scene.\n\n"
95 " :arg ini: the initial scene foor the transition.\n"
96 " :type ini: int\n"
97 " :arg end: The final scene for the transition.\n"
98 " :type end: int\n"
99 " :arg transition: The transition sound.\n"
100 " :type transition: :class:`Sound`\n"
101 " :return: false if the ini or end scenes don't exist, true othrwise.\n"
102 " :rtype: bool");
103
104 static PyObject *
DynamicMusic_addTransition(DynamicMusicP * self,PyObject * args)105 DynamicMusic_addTransition(DynamicMusicP* self, PyObject* args)
106 {
107 PyObject* object;
108 int ini, end;
109 if(!PyArg_ParseTuple(args, "iiO:sound", &ini, &end, &object))
110 return nullptr;
111 Sound* sound = checkSound(object);
112 if(!sound)
113 return nullptr;
114
115 try
116 {
117 (*reinterpret_cast<std::shared_ptr<aud::DynamicMusic>*>(self->dynamicMusic))->addTransition(ini, end, *reinterpret_cast<std::shared_ptr<aud::ISound>*>(sound->sound));
118 Py_RETURN_NONE;
119 }
120 catch(aud::Exception& e)
121 {
122 PyErr_SetString(AUDError, e.what());
123 return nullptr;
124 }
125 }
126
127 PyDoc_STRVAR(M_aud_DynamicMusic_resume_doc,
128 ".. classmethod:: resume()\n\n"
129 " Resumes playback of the scene.\n\n"
130 " :return: Whether the action succeeded.\n"
131 " :rtype: bool");
132
133 static PyObject *
DynamicMusic_resume(DynamicMusicP * self)134 DynamicMusic_resume(DynamicMusicP* self)
135 {
136 try
137 {
138 return PyBool_FromLong((long)(*reinterpret_cast<std::shared_ptr<aud::DynamicMusic>*>(self->dynamicMusic))->resume());
139 }
140 catch(aud::Exception& e)
141 {
142 PyErr_SetString(AUDError, e.what());
143 return nullptr;
144 }
145 }
146
147 PyDoc_STRVAR(M_aud_DynamicMusic_pause_doc,
148 ".. classmethod:: pause()\n\n"
149 " Pauses playback of the scene.\n\n"
150 " :return: Whether the action succeeded.\n"
151 " :rtype: bool");
152
153 static PyObject *
DynamicMusic_pause(DynamicMusicP * self)154 DynamicMusic_pause(DynamicMusicP* self)
155 {
156 try
157 {
158 return PyBool_FromLong((long)(*reinterpret_cast<std::shared_ptr<aud::DynamicMusic>*>(self->dynamicMusic))->pause());
159 }
160 catch(aud::Exception& e)
161 {
162 PyErr_SetString(AUDError, e.what());
163 return nullptr;
164 }
165 }
166
167 PyDoc_STRVAR(M_aud_DynamicMusic_stop_doc,
168 ".. classmethod:: stop()\n\n"
169 " Stops playback of the scene.\n\n"
170 " :return: Whether the action succeeded.\n"
171 " :rtype: bool\n\n");
172
173 static PyObject *
DynamicMusic_stop(DynamicMusicP * self)174 DynamicMusic_stop(DynamicMusicP* self)
175 {
176 try
177 {
178 return PyBool_FromLong((long)(*reinterpret_cast<std::shared_ptr<aud::DynamicMusic>*>(self->dynamicMusic))->stop());
179 }
180 catch(aud::Exception& e)
181 {
182 PyErr_SetString(AUDError, e.what());
183 return nullptr;
184 }
185 }
186
187 static PyMethodDef DynamicMusic_methods[] = {
188 { "addScene", (PyCFunction)DynamicMusic_addScene, METH_O,
189 M_aud_DynamicMusic_addScene_doc
190 },
191 { "addTransition", (PyCFunction)DynamicMusic_addTransition, METH_VARARGS,
192 M_aud_DynamicMusic_addTransition_doc
193 },
194 { "resume", (PyCFunction)DynamicMusic_resume, METH_NOARGS,
195 M_aud_DynamicMusic_resume_doc
196 },
197 { "pause", (PyCFunction)DynamicMusic_pause, METH_NOARGS,
198 M_aud_DynamicMusic_pause_doc
199 },
200 { "stop", (PyCFunction)DynamicMusic_stop, METH_NOARGS,
201 M_aud_DynamicMusic_stop_doc
202 },
203 { nullptr } /* Sentinel */
204 };
205
206 /////////////////////////////////////////////////////
207
208 PyDoc_STRVAR(M_aud_DynamicMusic_status_doc,
209 "Whether the scene is playing, paused or stopped (=invalid).");
210
211 static PyObject *
DynamicMusic_get_status(DynamicMusicP * self,void * nothing)212 DynamicMusic_get_status(DynamicMusicP* self, void* nothing)
213 {
214 try
215 {
216 return PyBool_FromLong((long)(*reinterpret_cast<std::shared_ptr<aud::DynamicMusic>*>(self->dynamicMusic))->getStatus());
217 }
218 catch(aud::Exception& e)
219 {
220 PyErr_SetString(AUDError, e.what());
221 return nullptr;
222 }
223 }
224
225 PyDoc_STRVAR(M_aud_DynamicMusic_position_doc,
226 "The playback position of the scene in seconds.");
227
228 static int
DynamicMusic_set_position(DynamicMusicP * self,PyObject * args,void * nothing)229 DynamicMusic_set_position(DynamicMusicP* self, PyObject* args, void* nothing)
230 {
231 double position;
232
233 if(!PyArg_Parse(args, "d:position", &position))
234 return -1;
235
236 try
237 {
238 if((*reinterpret_cast<std::shared_ptr<aud::DynamicMusic>*>(self->dynamicMusic))->seek(position))
239 return 0;
240 PyErr_SetString(AUDError, "Couldn't seek the sound!");
241 }
242 catch(aud::Exception& e)
243 {
244 PyErr_SetString(AUDError, e.what());
245 }
246
247 return -1;
248 }
249
250 static PyObject *
DynamicMusic_get_position(DynamicMusicP * self,void * nothing)251 DynamicMusic_get_position(DynamicMusicP* self, void* nothing)
252 {
253 try
254 {
255 return Py_BuildValue("d", (*reinterpret_cast<std::shared_ptr<aud::DynamicMusic>*>(self->dynamicMusic))->getPosition());
256 }
257 catch(aud::Exception& e)
258 {
259 PyErr_SetString(AUDError, e.what());
260 return nullptr;
261 }
262 }
263
264 PyDoc_STRVAR(M_aud_DynamicMusic_fadeTime_doc,
265 "The length in seconds of the crossfade transition");
266
267 static int
DynamicMusic_set_fadeTime(DynamicMusicP * self,PyObject * args,void * nothing)268 DynamicMusic_set_fadeTime(DynamicMusicP* self, PyObject* args, void* nothing)
269 {
270 float fadeTime;
271
272 if(!PyArg_Parse(args, "f:fadeTime", &fadeTime))
273 return -1;
274
275 try
276 {
277 (*reinterpret_cast<std::shared_ptr<aud::DynamicMusic>*>(self->dynamicMusic))->setFadeTime(fadeTime);
278 return 0;
279 }
280 catch(aud::Exception& e)
281 {
282 PyErr_SetString(AUDError, e.what());
283 }
284
285 return -1;
286 }
287
288 static PyObject *
DynamicMusic_get_fadeTime(DynamicMusicP * self,void * nothing)289 DynamicMusic_get_fadeTime(DynamicMusicP* self, void* nothing)
290 {
291 try
292 {
293 return Py_BuildValue("f", (*reinterpret_cast<std::shared_ptr<aud::DynamicMusic>*>(self->dynamicMusic))->getFadeTime());
294 }
295 catch(aud::Exception& e)
296 {
297 PyErr_SetString(AUDError, e.what());
298 return nullptr;
299 }
300 }
301
302 PyDoc_STRVAR(M_aud_DynamicMusic_scene_doc,
303 "The current scene");
304
305 static int
DynamicMusic_set_scene(DynamicMusicP * self,PyObject * args,void * nothing)306 DynamicMusic_set_scene(DynamicMusicP* self, PyObject* args, void* nothing)
307 {
308 int scene;
309
310 if(!PyArg_Parse(args, "i:scene", &scene))
311 return -1;
312
313 try
314 {
315 if((*reinterpret_cast<std::shared_ptr<aud::DynamicMusic>*>(self->dynamicMusic))->changeScene(scene))
316 return 0;
317 PyErr_SetString(AUDError, "Couldn't change the scene!");
318 }
319 catch(aud::Exception& e)
320 {
321 PyErr_SetString(AUDError, e.what());
322 }
323
324 return -1;
325 }
326
327 static PyObject *
DynamicMusic_get_scene(DynamicMusicP * self,void * nothing)328 DynamicMusic_get_scene(DynamicMusicP* self, void* nothing)
329 {
330 try
331 {
332 return Py_BuildValue("i", (*reinterpret_cast<std::shared_ptr<aud::DynamicMusic>*>(self->dynamicMusic))->getScene());
333 }
334 catch(aud::Exception& e)
335 {
336 PyErr_SetString(AUDError, e.what());
337 return nullptr;
338 }
339 }
340
341 PyDoc_STRVAR(M_aud_DynamicMusic_volume_doc,
342 "The volume of the scene.");
343
344 static int
DynamicMusic_set_volume(DynamicMusicP * self,PyObject * args,void * nothing)345 DynamicMusic_set_volume(DynamicMusicP* self, PyObject* args, void* nothing)
346 {
347 float volume;
348
349 if(!PyArg_Parse(args, "f:volume", &volume))
350 return -1;
351
352 try
353 {
354 if((*reinterpret_cast<std::shared_ptr<aud::DynamicMusic>*>(self->dynamicMusic))->setVolume(volume))
355 return 0;
356 PyErr_SetString(AUDError, "Couldn't change the volume!");
357 }
358 catch(aud::Exception& e)
359 {
360 PyErr_SetString(AUDError, e.what());
361 }
362
363 return -1;
364 }
365
366 static PyObject *
DynamicMusic_get_volume(DynamicMusicP * self,void * nothing)367 DynamicMusic_get_volume(DynamicMusicP* self, void* nothing)
368 {
369 try
370 {
371 return Py_BuildValue("f", (*reinterpret_cast<std::shared_ptr<aud::DynamicMusic>*>(self->dynamicMusic))->getVolume());
372 }
373 catch(aud::Exception& e)
374 {
375 PyErr_SetString(AUDError, e.what());
376 return nullptr;
377 }
378 }
379
380 static PyGetSetDef DynamicMusic_properties[] = {
381 { (char*)"status", (getter)DynamicMusic_get_status, nullptr,
382 M_aud_DynamicMusic_status_doc, nullptr },
383 { (char*)"position", (getter)DynamicMusic_get_position, (setter)DynamicMusic_set_position,
384 M_aud_DynamicMusic_position_doc, nullptr },
385 { (char*)"fadeTime", (getter)DynamicMusic_get_fadeTime, (setter)DynamicMusic_set_fadeTime,
386 M_aud_DynamicMusic_fadeTime_doc, nullptr },
387 { (char*)"scene", (getter)DynamicMusic_get_scene, (setter)DynamicMusic_set_scene,
388 M_aud_DynamicMusic_scene_doc, nullptr },
389 { (char*)"volume", (getter)DynamicMusic_get_volume, (setter)DynamicMusic_set_volume,
390 M_aud_DynamicMusic_volume_doc, nullptr },
391 { nullptr } /* Sentinel */
392 };
393
394 PyDoc_STRVAR(M_aud_DynamicMusic_doc,
395 "The DynamicMusic object allows to play music depending on a current scene, scene changes are managed by the class, with the possibility of custom transitions.\n"
396 "The default transition is a crossfade effect, and the default scene is silent and has id 0");
397
398 PyTypeObject DynamicMusicType = {
399 PyVarObject_HEAD_INIT(nullptr, 0)
400 "aud.DynamicMusic", /* tp_name */
401 sizeof(DynamicMusicP), /* tp_basicsize */
402 0, /* tp_itemsize */
403 (destructor)DynamicMusic_dealloc, /* tp_dealloc */
404 0, /* tp_print */
405 0, /* tp_getattr */
406 0, /* tp_setattr */
407 0, /* tp_reserved */
408 0, /* tp_repr */
409 0, /* tp_as_number */
410 0, /* tp_as_sequence */
411 0, /* tp_as_mapping */
412 0, /* tp_hash */
413 0, /* tp_call */
414 0, /* tp_str */
415 0, /* tp_getattro */
416 0, /* tp_setattro */
417 0, /* tp_as_buffer */
418 Py_TPFLAGS_DEFAULT, /* tp_flags */
419 M_aud_DynamicMusic_doc, /* tp_doc */
420 0, /* tp_traverse */
421 0, /* tp_clear */
422 0, /* tp_richcompare */
423 0, /* tp_weaklistoffset */
424 0, /* tp_iter */
425 0, /* tp_iternext */
426 DynamicMusic_methods, /* tp_methods */
427 0, /* tp_members */
428 DynamicMusic_properties, /* tp_getset */
429 0, /* tp_base */
430 0, /* tp_dict */
431 0, /* tp_descr_get */
432 0, /* tp_descr_set */
433 0, /* tp_dictoffset */
434 0, /* tp_init */
435 0, /* tp_alloc */
436 DynamicMusic_new, /* tp_new */
437 };
438
DynamicMusic_empty()439 AUD_API PyObject* DynamicMusic_empty()
440 {
441 return DynamicMusicType.tp_alloc(&DynamicMusicType, 0);
442 }
443
444
checkDynamicMusic(PyObject * dynamicMusic)445 AUD_API DynamicMusicP* checkDynamicMusic(PyObject* dynamicMusic)
446 {
447 if(!PyObject_TypeCheck(dynamicMusic, &DynamicMusicType))
448 {
449 PyErr_SetString(PyExc_TypeError, "Object is not of type DynamicMusic!");
450 return nullptr;
451 }
452
453 return (DynamicMusicP*)dynamicMusic;
454 }
455
456
initializeDynamicMusic()457 bool initializeDynamicMusic()
458 {
459 return PyType_Ready(&DynamicMusicType) >= 0;
460 }
461
462
addDynamicMusicToModule(PyObject * module)463 void addDynamicMusicToModule(PyObject* module)
464 {
465 Py_INCREF(&DynamicMusicType);
466 PyModule_AddObject(module, "DynamicMusic", (PyObject *)&DynamicMusicType);
467 }
468