Switch fixed time system. Logic updates should now happen at 30Hz, physics at 60Hz...
[blender.git] / source / gameengine / Ketsji / KX_SoundActuator.cpp
1 /**
2  * KX_SoundActuator.cpp
3  *
4  * $Id$
5  *
6  * ***** BEGIN GPL/BL DUAL 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. The Blender
12  * Foundation also sells licenses for use in proprietary software under
13  * the Blender License.  See http://www.blender.org/BL/ for information
14  * about this.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software Foundation,
23  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  *
25  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
26  * All rights reserved.
27  *
28  * The Original Code is: all of this file.
29  *
30  * Contributor(s): none yet.
31  *
32  * ***** END GPL/BL DUAL LICENSE BLOCK *****
33  *
34  */
35
36 #include "KX_SoundActuator.h"
37 #include "SND_SoundObject.h"
38 #include "KX_GameObject.h"
39 #include "SND_SoundObject.h"
40 #include "SND_Scene.h" // needed for replication
41 #include <iostream>
42
43 #ifdef HAVE_CONFIG_H
44 #include <config.h>
45 #endif
46
47 /* ------------------------------------------------------------------------- */
48 /* Native functions                                                          */
49 /* ------------------------------------------------------------------------- */
50 KX_SoundActuator::KX_SoundActuator(SCA_IObject* gameobj,
51                                                                    SND_SoundObject* sndobj,
52                                                                    SND_Scene*   sndscene,
53                                                                    KX_SOUNDACT_TYPE type,
54                                                                    short start,
55                                                                    short end,
56                                                                    PyTypeObject* T)
57                                                                    : SCA_IActuator(gameobj,T)
58 {
59         m_soundObject = sndobj;
60         m_soundScene = sndscene;
61         m_type = type;
62         m_lastEvent = true;
63         m_isplaying = false;
64         m_startFrame = start;
65         m_endFrame = end;
66         m_pino = false;
67 }
68
69
70
71 KX_SoundActuator::~KX_SoundActuator()
72 {
73         //m_soundScene->RemoveObject(this->m_soundObject);
74         //(this->m_soundObject)->DeleteWhenFinished();
75         m_soundScene->RemoveActiveObject(m_soundObject);
76 //      m_soundScene->DeleteObjectWhenFinished(m_soundObject);
77         m_soundScene->DeleteObject(m_soundObject);
78 }
79
80
81
82 CValue* KX_SoundActuator::GetReplica()
83 {
84         KX_SoundActuator* replica = new KX_SoundActuator(*this);
85         replica->ProcessReplica();
86         SND_SoundObject* soundobj = new SND_SoundObject(*m_soundObject);
87         replica->setSoundObject(soundobj);
88         m_soundScene->AddObject(soundobj);
89         
90         // this will copy properties and so on...
91         CValue::AddDataToReplica(replica);
92         return replica;
93 };
94
95
96
97 bool KX_SoundActuator::Update(double curtime, bool frame)
98 {
99         if (!frame)
100                 return true;
101         bool result = false;
102
103         // do nothing on negative events, otherwise sounds are played twice!
104         bool bNegativeEvent = IsNegativeEvent();
105
106         RemoveAllEvents();
107
108         if (m_pino)
109         {
110                 bNegativeEvent = true;
111                 m_pino = false;
112         }
113
114         if (bNegativeEvent)
115         {       
116                 // here must be a check if it is still playing
117                 m_isplaying = false;
118
119                 switch (m_type)
120                 {
121                 case KX_SOUNDACT_PLAYSTOP:
122                 case KX_SOUNDACT_LOOPSTOP:
123                 case KX_SOUNDACT_LOOPBIDIRECTIONAL_STOP:
124                         {
125                                 m_soundScene->RemoveActiveObject(m_soundObject);
126                                 break;
127                         }
128                 case KX_SOUNDACT_PLAYEND:
129                         {
130                                 m_soundObject->SetPlaystate(SND_MUST_STOP_WHEN_FINISHED);
131                                 break;
132                         }
133                 default:
134                         // implement me !!
135                         break;
136                 }
137         }
138         else
139         {
140                 if (m_soundObject && !m_isplaying)
141                 {
142                         switch (m_type)
143                         {
144                         case KX_SOUNDACT_LOOPBIDIRECTIONAL:
145                         case KX_SOUNDACT_LOOPBIDIRECTIONAL_STOP:
146                                 {
147                                         m_soundObject->SetLoopMode(SND_LOOP_BIDIRECTIONAL);
148                                         m_soundScene->AddActiveObject(m_soundObject, curtime);
149                                         m_isplaying = true;
150                                         result = true;
151                                         break;
152                                 }
153                         case KX_SOUNDACT_LOOPEND:
154                         case KX_SOUNDACT_LOOPSTOP:
155                                 {
156                                         m_soundObject->SetLoopMode(SND_LOOP_NORMAL);
157                                         m_soundScene->AddActiveObject(m_soundObject, curtime);
158                                         m_isplaying = true;
159                                         result = true;
160                                         break;
161                                 }
162                         case KX_SOUNDACT_PLAYSTOP:
163                         case KX_SOUNDACT_PLAYEND:
164                                 {
165                                         m_soundObject->SetLoopMode(SND_LOOP_OFF);
166                                         m_soundScene->AddActiveObject(m_soundObject, curtime);
167                                         m_isplaying = true;
168                                         result = true;
169                                         break;
170                                 }
171                         default:
172                                 // implement me !!
173                                 break;
174                         }
175                 }
176         }
177
178         if (m_isplaying)
179         {
180                 m_soundObject->SetPosition(((KX_GameObject*)this->GetParent())->NodeGetWorldPosition());
181                 m_soundObject->SetVelocity(((KX_GameObject*)this->GetParent())->GetLinearVelocity());
182                 m_soundObject->SetOrientation(((KX_GameObject*)this->GetParent())->NodeGetWorldOrientation());
183                 result = true;
184         }
185         else
186         {
187                 result = false;
188         }
189
190         if (result && (m_soundObject->IsLifeSpanOver(curtime)) && ((m_type == KX_SOUNDACT_PLAYEND) || (m_type == KX_SOUNDACT_PLAYSTOP)))
191         {
192                 m_pino = true;
193         }
194
195         return result;
196 }
197
198
199
200 void KX_SoundActuator::setSoundObject(class SND_SoundObject* soundobject)
201 {
202         m_soundObject = soundobject;
203 }
204
205
206
207 /* ------------------------------------------------------------------------- */
208 /* Python functions                                                          */
209 /* ------------------------------------------------------------------------- */
210
211
212
213 /* Integration hooks ------------------------------------------------------- */
214 PyTypeObject KX_SoundActuator::Type = {
215         PyObject_HEAD_INIT(&PyType_Type)
216                 0,
217                 "KX_SoundActuator",
218                 sizeof(KX_SoundActuator),
219                 0,
220                 PyDestructor,
221                 0,
222                 __getattr,
223                 __setattr,
224                 0, //&MyPyCompare,
225                 __repr,
226                 0, //&cvalue_as_number,
227                 0,
228                 0,
229                 0,
230                 0
231 };
232
233
234
235 PyParentObject KX_SoundActuator::Parents[] = {
236         &KX_SoundActuator::Type,
237                 &SCA_IActuator::Type,
238                 &SCA_ILogicBrick::Type,
239                 &CValue::Type,
240                 NULL
241 };
242
243
244
245 PyMethodDef KX_SoundActuator::Methods[] = {
246         {"setFilename", (PyCFunction) KX_SoundActuator::sPySetFilename, METH_VARARGS,NULL},
247         {"getFilename", (PyCFunction) KX_SoundActuator::sPyGetFilename, METH_VARARGS,NULL},
248         {"startSound",(PyCFunction) KX_SoundActuator::sPyStartSound,METH_VARARGS,NULL},
249         {"pauseSound",(PyCFunction) KX_SoundActuator::sPyPauseSound,METH_VARARGS,NULL},
250         {"stopSound",(PyCFunction) KX_SoundActuator::sPyStopSound,METH_VARARGS,NULL},
251         {"setGain",(PyCFunction) KX_SoundActuator::sPySetGain,METH_VARARGS,NULL},
252         {"getGain",(PyCFunction) KX_SoundActuator::sPyGetGain,METH_VARARGS,NULL},
253         {"setPitch",(PyCFunction) KX_SoundActuator::sPySetPitch,METH_VARARGS,NULL},
254         {"getPitch",(PyCFunction) KX_SoundActuator::sPyGetPitch,METH_VARARGS,NULL},
255         {"setRollOffFactor",(PyCFunction) KX_SoundActuator::sPySetRollOffFactor,METH_VARARGS,NULL},
256         {"getRollOffFactor",(PyCFunction) KX_SoundActuator::sPyGetRollOffFactor,METH_VARARGS,NULL},
257         {"setLooping",(PyCFunction) KX_SoundActuator::sPySetLooping,METH_VARARGS,NULL},
258         {"getLooping",(PyCFunction) KX_SoundActuator::sPyGetLooping,METH_VARARGS,NULL},
259         {"setPosition",(PyCFunction) KX_SoundActuator::sPySetPosition,METH_VARARGS,NULL},
260         {"setVelocity",(PyCFunction) KX_SoundActuator::sPySetVelocity,METH_VARARGS,NULL},
261         {"setOrientation",(PyCFunction) KX_SoundActuator::sPySetOrientation,METH_VARARGS,NULL},
262         {"setType",(PyCFunction) KX_SoundActuator::sPySetType,METH_VARARGS,NULL},
263         {"getType",(PyCFunction) KX_SoundActuator::sPyGetType,METH_VARARGS,NULL},
264         {NULL,NULL,NULL,NULL} //Sentinel
265 };
266
267
268
269 PyObject* KX_SoundActuator::_getattr(const STR_String& attr)
270 {
271         _getattr_up(SCA_IActuator);
272 }
273
274
275
276 PyObject* KX_SoundActuator::PySetFilename(PyObject* self, PyObject* args, PyObject* kwds)
277 {
278         char *soundName = NULL;
279         void *soundPointer = NULL;
280         
281         if (!PyArg_ParseTuple(args, "s", &soundName))
282                 return NULL;
283
284         Py_Return;
285 }
286
287
288
289 PyObject* KX_SoundActuator::PyGetFilename(PyObject* self, PyObject* args, PyObject* kwds)
290 {
291         STR_String objectname = m_soundObject->GetObjectName();
292         char* name = objectname.Ptr();
293         
294         if (!name) {
295                 Py_Return;                                      /* internal error */
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