Merged 15170:15635 from trunk (no conflicts or even merges)
[blender.git] / source / gameengine / Ketsji / KX_SoundActuator.cpp
1 /**
2  * KX_SoundActuator.cpp
3  *
4  * $Id$
5  *
6  * ***** BEGIN GPL LICENSE BLOCK *****
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software Foundation,
20  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21  *
22  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
23  * All rights reserved.
24  *
25  * The Original Code is: all of this file.
26  *
27  * Contributor(s): none yet.
28  *
29  * ***** END GPL LICENSE BLOCK *****
30  *
31  */
32
33 #include "KX_SoundActuator.h"
34 #include "SND_SoundObject.h"
35 #include "KX_GameObject.h"
36 #include "SND_SoundObject.h"
37 #include "SND_Scene.h" // needed for replication
38 #include <iostream>
39
40 #ifdef HAVE_CONFIG_H
41 #include <config.h>
42 #endif
43
44 /* ------------------------------------------------------------------------- */
45 /* Native functions                                                          */
46 /* ------------------------------------------------------------------------- */
47 KX_SoundActuator::KX_SoundActuator(SCA_IObject* gameobj,
48                                                                    SND_SoundObject* sndobj,
49                                                                    SND_Scene*   sndscene,
50                                                                    KX_SOUNDACT_TYPE type,
51                                                                    short start,
52                                                                    short end,
53                                                                    PyTypeObject* T)
54                                                                    : SCA_IActuator(gameobj,T)
55 {
56         m_soundObject = sndobj;
57         m_soundScene = sndscene;
58         m_type = type;
59         m_lastEvent = true;
60         m_isplaying = false;
61         m_startFrame = start;
62         m_endFrame = end;
63         m_pino = false;
64         
65
66 }
67
68
69
70 KX_SoundActuator::~KX_SoundActuator()
71 {
72         //m_soundScene->RemoveObject(this->m_soundObject);
73         //(this->m_soundObject)->DeleteWhenFinished();
74         m_soundScene->RemoveActiveObject(m_soundObject);
75 //      m_soundScene->DeleteObjectWhenFinished(m_soundObject);
76         m_soundScene->DeleteObject(m_soundObject);
77 }
78
79
80
81 CValue* KX_SoundActuator::GetReplica()
82 {
83         KX_SoundActuator* replica = new KX_SoundActuator(*this);
84         replica->ProcessReplica();
85         SND_SoundObject* soundobj = new SND_SoundObject(*m_soundObject);
86         replica->setSoundObject(soundobj);
87         m_soundScene->AddObject(soundobj);
88         
89         // this will copy properties and so on...
90         CValue::AddDataToReplica(replica);
91         return replica;
92 };
93
94
95
96 bool KX_SoundActuator::Update(double curtime, bool frame)
97 {
98         if (!frame)
99                 return true;
100         bool result = false;
101
102         // do nothing on negative events, otherwise sounds are played twice!
103         bool bNegativeEvent = IsNegativeEvent();
104
105         RemoveAllEvents();
106
107         if (m_pino)
108         {
109                 bNegativeEvent = true;
110                 m_pino = false;
111         }
112
113         if (bNegativeEvent)
114         {       
115                 // here must be a check if it is still playing
116                 m_isplaying = false;
117
118                 switch (m_type)
119                 {
120                 case KX_SOUNDACT_PLAYSTOP:
121                 case KX_SOUNDACT_LOOPSTOP:
122                 case KX_SOUNDACT_LOOPBIDIRECTIONAL_STOP:
123                         {
124                                 m_soundScene->RemoveActiveObject(m_soundObject);
125                                 break;
126                         }
127                 case KX_SOUNDACT_PLAYEND:
128                         {
129                                 m_soundObject->SetPlaystate(SND_MUST_STOP_WHEN_FINISHED);
130                                 break;
131                         }
132                 default:
133                         // implement me !!
134                         break;
135                 }
136         }
137         else
138         {
139                 if (m_soundObject && !m_isplaying)
140                 {
141                         switch (m_type)
142                         {
143                         case KX_SOUNDACT_LOOPBIDIRECTIONAL:
144                         case KX_SOUNDACT_LOOPBIDIRECTIONAL_STOP:
145                                 {
146                                         m_soundObject->SetLoopMode(SND_LOOP_BIDIRECTIONAL);
147                                         m_soundScene->AddActiveObject(m_soundObject, curtime);
148                                         m_isplaying = true;
149                                         result = true;
150                                         break;
151                                 }
152                         case KX_SOUNDACT_LOOPEND:
153                         case KX_SOUNDACT_LOOPSTOP:
154                                 {
155                                         m_soundObject->SetLoopMode(SND_LOOP_NORMAL);
156                                         m_soundScene->AddActiveObject(m_soundObject, curtime);
157                                         m_isplaying = true;
158                                         result = true;
159                                         break;
160                                 }
161                         case KX_SOUNDACT_PLAYSTOP:
162                         case KX_SOUNDACT_PLAYEND:
163                                 {
164                                         m_soundObject->SetLoopMode(SND_LOOP_OFF);
165                                         m_soundScene->AddActiveObject(m_soundObject, curtime);
166                                         m_isplaying = true;
167                                         result = true;
168                                         break;
169                                 }
170                         default:
171                                 // implement me !!
172                                 break;
173                         }
174                 }
175         }
176
177         if (m_isplaying)
178         {
179                 m_soundObject->SetPosition(((KX_GameObject*)this->GetParent())->NodeGetWorldPosition());
180                 m_soundObject->SetVelocity(((KX_GameObject*)this->GetParent())->GetLinearVelocity());
181                 m_soundObject->SetOrientation(((KX_GameObject*)this->GetParent())->NodeGetWorldOrientation());
182                 result = true;
183         }
184         else
185         {
186                 result = false;
187         }
188
189         if (result && (m_soundObject->IsLifeSpanOver(curtime)) && ((m_type == KX_SOUNDACT_PLAYEND) || (m_type == KX_SOUNDACT_PLAYSTOP)))
190         {
191                 m_pino = true;
192         }
193
194         return result;
195 }
196
197
198
199 void KX_SoundActuator::setSoundObject(class SND_SoundObject* soundobject)
200 {
201         m_soundObject = soundobject;
202 }
203
204
205
206 /* ------------------------------------------------------------------------- */
207 /* Python functions                                                          */
208 /* ------------------------------------------------------------------------- */
209
210
211
212 /* Integration hooks ------------------------------------------------------- */
213 PyTypeObject KX_SoundActuator::Type = {
214         PyObject_HEAD_INIT(&PyType_Type)
215                 0,
216                 "KX_SoundActuator",
217                 sizeof(KX_SoundActuator),
218                 0,
219                 PyDestructor,
220                 0,
221                 __getattr,
222                 __setattr,
223                 0, //&MyPyCompare,
224                 __repr,
225                 0, //&cvalue_as_number,
226                 0,
227                 0,
228                 0,
229                 0
230 };
231
232
233
234 PyParentObject KX_SoundActuator::Parents[] = {
235         &KX_SoundActuator::Type,
236                 &SCA_IActuator::Type,
237                 &SCA_ILogicBrick::Type,
238                 &CValue::Type,
239                 NULL
240 };
241
242
243
244 PyMethodDef KX_SoundActuator::Methods[] = {
245         {"setFilename", (PyCFunction) KX_SoundActuator::sPySetFilename, METH_VARARGS,NULL},
246         {"getFilename", (PyCFunction) KX_SoundActuator::sPyGetFilename, METH_VARARGS,NULL},
247         {"startSound",(PyCFunction) KX_SoundActuator::sPyStartSound,METH_VARARGS,NULL},
248         {"pauseSound",(PyCFunction) KX_SoundActuator::sPyPauseSound,METH_VARARGS,NULL},
249         {"stopSound",(PyCFunction) KX_SoundActuator::sPyStopSound,METH_VARARGS,NULL},
250         {"setGain",(PyCFunction) KX_SoundActuator::sPySetGain,METH_VARARGS,NULL},
251         {"getGain",(PyCFunction) KX_SoundActuator::sPyGetGain,METH_VARARGS,NULL},
252         {"setPitch",(PyCFunction) KX_SoundActuator::sPySetPitch,METH_VARARGS,NULL},
253         {"getPitch",(PyCFunction) KX_SoundActuator::sPyGetPitch,METH_VARARGS,NULL},
254         {"setRollOffFactor",(PyCFunction) KX_SoundActuator::sPySetRollOffFactor,METH_VARARGS,NULL},
255         {"getRollOffFactor",(PyCFunction) KX_SoundActuator::sPyGetRollOffFactor,METH_VARARGS,NULL},
256         {"setLooping",(PyCFunction) KX_SoundActuator::sPySetLooping,METH_VARARGS,NULL},
257         {"getLooping",(PyCFunction) KX_SoundActuator::sPyGetLooping,METH_VARARGS,NULL},
258         {"setPosition",(PyCFunction) KX_SoundActuator::sPySetPosition,METH_VARARGS,NULL},
259         {"setVelocity",(PyCFunction) KX_SoundActuator::sPySetVelocity,METH_VARARGS,NULL},
260         {"setOrientation",(PyCFunction) KX_SoundActuator::sPySetOrientation,METH_VARARGS,NULL},
261         {"setType",(PyCFunction) KX_SoundActuator::sPySetType,METH_VARARGS,NULL},
262         {"getType",(PyCFunction) KX_SoundActuator::sPyGetType,METH_VARARGS,NULL},
263         {NULL,NULL,NULL,NULL} //Sentinel
264 };
265
266
267
268 PyObject* KX_SoundActuator::_getattr(const STR_String& attr)
269 {
270         _getattr_up(SCA_IActuator);
271 }
272
273
274
275 PyObject* KX_SoundActuator::PySetFilename(PyObject* self, PyObject* args, PyObject* kwds)
276 {
277         char *soundName = NULL;
278         // void *soundPointer = NULL; /*unused*/
279         
280         if (!PyArg_ParseTuple(args, "s", &soundName))
281                 return NULL;
282
283         Py_Return;
284 }
285
286
287
288 PyObject* KX_SoundActuator::PyGetFilename(PyObject* self, PyObject* args, PyObject* kwds)
289 {
290         STR_String objectname = m_soundObject->GetObjectName();
291         char* name = objectname.Ptr();
292         
293         if (!name) {
294                 PyErr_SetString(PyExc_RuntimeError, "Unable to get sound filename");
295                 return NULL;
296         } else
297                 return PyString_FromString(name);
298 }
299
300
301
302 PyObject* KX_SoundActuator::PyStartSound(PyObject* self, PyObject* args, PyObject* kwds)
303 {
304         m_soundObject->StartSound();    
305         Py_Return;
306 }         
307
308
309
310 PyObject* KX_SoundActuator::PyPauseSound(PyObject* self, PyObject* args, PyObject* kwds)
311 {
312         m_soundObject->PauseSound();    
313         Py_Return;
314
315
316
317
318 PyObject* KX_SoundActuator::PyStopSound(PyObject* self, PyObject* args, PyObject* kwds)
319 {
320         m_soundObject->StopSound();     
321         Py_Return;
322 }
323
324
325
326 PyObject* KX_SoundActuator::PySetGain(PyObject* self, PyObject* args, PyObject* kwds)
327 {
328         float gain = 1.0;
329         if (!PyArg_ParseTuple(args, "f", &gain))
330                 return NULL;
331         
332         m_soundObject->SetGain(gain);
333         
334         Py_Return;
335 }         
336
337
338
339 PyObject* KX_SoundActuator::PyGetGain(PyObject* self, PyObject* args, PyObject* kwds)
340 {
341         float gain = m_soundObject->GetGain();
342         PyObject* result = PyFloat_FromDouble(gain);
343         
344         return result;
345 }
346
347
348
349 PyObject* KX_SoundActuator::PySetPitch(PyObject* self, PyObject* args, PyObject* kwds)
350 {
351         float pitch = 1.0;
352         if (!PyArg_ParseTuple(args, "f", &pitch))
353                 return NULL;
354         
355         m_soundObject->SetPitch(pitch);
356         
357         Py_Return;
358 }         
359
360
361
362 PyObject* KX_SoundActuator::PyGetPitch(PyObject* self, PyObject* args, PyObject* kwds)
363 {
364         float pitch = m_soundObject->GetPitch();
365         PyObject* result = PyFloat_FromDouble(pitch);
366         
367         return result;
368 }
369
370
371
372 PyObject* KX_SoundActuator::PySetRollOffFactor(PyObject* self, PyObject* args, PyObject* kwds)
373 {
374         float rollofffactor = 1.0;
375         if (!PyArg_ParseTuple(args, "f", &rollofffactor))
376                 return NULL;
377         
378         m_soundObject->SetRollOffFactor(rollofffactor);
379
380         Py_Return;
381 }         
382
383
384
385 PyObject* KX_SoundActuator::PyGetRollOffFactor(PyObject* self, PyObject* args, PyObject* kwds)
386 {
387         float rollofffactor = m_soundObject->GetRollOffFactor();
388         PyObject* result = PyFloat_FromDouble(rollofffactor);
389         
390         return result;
391 }
392
393
394
395 PyObject* KX_SoundActuator::PySetLooping(PyObject* self, PyObject* args, PyObject* kwds)
396 {
397         bool looping = 1;
398         if (!PyArg_ParseTuple(args, "i", &looping))
399                 return NULL;
400         
401         m_soundObject->SetLoopMode(looping);
402         
403         Py_Return;
404 }         
405
406
407
408 PyObject* KX_SoundActuator::PyGetLooping(PyObject* self, PyObject* args, PyObject* kwds)
409 {
410         int looping = m_soundObject->GetLoopMode();
411         PyObject* result = PyInt_FromLong(looping);
412         
413         return result;
414 }
415
416
417
418 PyObject* KX_SoundActuator::PySetPosition(PyObject* self, PyObject* args, PyObject* kwds)
419 {
420         MT_Point3 pos;
421         pos[0] = 0.0;
422         pos[1] = 0.0;
423         pos[2] = 0.0;
424
425         if (!PyArg_ParseTuple(args, "fff", &pos[0], &pos[1], &pos[2]))
426                 return NULL;
427         
428         m_soundObject->SetPosition(pos);
429         
430         Py_Return;
431 }         
432
433
434
435 PyObject* KX_SoundActuator::PySetVelocity(PyObject* self, PyObject* args, PyObject* kwds)
436 {
437         MT_Vector3 vel;
438         vel[0] = 0.0;
439         vel[1] = 0.0;
440         vel[2] = 0.0;
441
442         if (!PyArg_ParseTuple(args, "fff", &vel[0], &vel[1], &vel[2]))
443                 return NULL;
444         
445         m_soundObject->SetVelocity(vel);
446         
447         Py_Return;
448 }         
449
450
451
452 PyObject* KX_SoundActuator::PySetOrientation(PyObject* self, PyObject* args, PyObject* kwds)
453 {
454         MT_Matrix3x3 ori;
455         ori[0][0] = 1.0;
456         ori[0][1] = 0.0;
457         ori[0][2] = 0.0;
458         ori[1][0] = 0.0;
459         ori[1][1] = 1.0;
460         ori[1][2] = 0.0;
461         ori[2][0] = 0.0;
462         ori[2][1] = 0.0;
463         ori[2][2] = 1.0;
464
465         if (!PyArg_ParseTuple(args, "fffffffff", &ori[0][0], &ori[0][1], &ori[0][2], &ori[1][0], &ori[1][1], &ori[1][2], &ori[2][0], &ori[2][1], &ori[2][2]))
466                 return NULL;
467         
468         m_soundObject->SetOrientation(ori);
469         
470         Py_Return;
471 }
472
473 PyObject* KX_SoundActuator::PySetType(PyObject* self, PyObject* args, PyObject* kwds)
474 {
475         int typeArg;
476
477         if (!PyArg_ParseTuple(args, "i", &typeArg)) {
478                 return NULL;
479         }
480
481         if ( (typeArg > KX_SOUNDACT_NODEF)
482           && (typeArg < KX_SOUNDACT_MAX) ) {
483                 m_type = (KX_SOUNDACT_TYPE) typeArg;
484         }
485
486         Py_Return;
487 }
488
489 PyObject* KX_SoundActuator::PyGetType(PyObject* self, PyObject* args, PyObject* kwds)
490 {
491         return PyInt_FromLong(m_type);
492 }
493
494
495