svn merge -r 16231:16536 https://svn.blender.org/svnroot/bf-blender/trunk/blender
[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         if (m_soundObject)
73         {
74                 m_soundScene->RemoveActiveObject(m_soundObject);
75                 m_soundScene->DeleteObject(m_soundObject);
76         }
77 }
78
79
80
81 CValue* KX_SoundActuator::GetReplica()
82 {
83         KX_SoundActuator* replica = new KX_SoundActuator(*this);
84         replica->ProcessReplica();
85         if (m_soundObject)
86         {
87             SND_SoundObject* soundobj = new SND_SoundObject(*m_soundObject);
88                 replica->setSoundObject(soundobj);
89                 m_soundScene->AddObject(soundobj);
90         }
91         
92         // this will copy properties and so on...
93         CValue::AddDataToReplica(replica);
94         return replica;
95 };
96
97
98
99 bool KX_SoundActuator::Update(double curtime, bool frame)
100 {
101         if (!frame)
102                 return true;
103         bool result = false;
104
105         // do nothing on negative events, otherwise sounds are played twice!
106         bool bNegativeEvent = IsNegativeEvent();
107
108         RemoveAllEvents();
109
110         if (!m_soundObject)
111                 return false;
112
113         if (m_pino)
114         {
115                 bNegativeEvent = true;
116                 m_pino = false;
117         }
118
119         if (bNegativeEvent)
120         {       
121                 // here must be a check if it is still playing
122                 m_isplaying = false;
123
124                 switch (m_type)
125                 {
126                 case KX_SOUNDACT_PLAYSTOP:
127                 case KX_SOUNDACT_LOOPSTOP:
128                 case KX_SOUNDACT_LOOPBIDIRECTIONAL_STOP:
129                         {
130                                 m_soundScene->RemoveActiveObject(m_soundObject);
131                                 break;
132                         }
133                 case KX_SOUNDACT_PLAYEND:
134                         {
135                                 m_soundObject->SetPlaystate(SND_MUST_STOP_WHEN_FINISHED);
136                                 break;
137                         }
138                 default:
139                         // implement me !!
140                         break;
141                 }
142         }
143         else
144         {
145                 if (m_soundObject && !m_isplaying)
146                 {
147                         switch (m_type)
148                         {
149                         case KX_SOUNDACT_LOOPBIDIRECTIONAL:
150                         case KX_SOUNDACT_LOOPBIDIRECTIONAL_STOP:
151                                 {
152                                         m_soundObject->SetLoopMode(SND_LOOP_BIDIRECTIONAL);
153                                         m_soundScene->AddActiveObject(m_soundObject, curtime);
154                                         m_isplaying = true;
155                                         result = true;
156                                         break;
157                                 }
158                         case KX_SOUNDACT_LOOPEND:
159                         case KX_SOUNDACT_LOOPSTOP:
160                                 {
161                                         m_soundObject->SetLoopMode(SND_LOOP_NORMAL);
162                                         m_soundScene->AddActiveObject(m_soundObject, curtime);
163                                         m_isplaying = true;
164                                         result = true;
165                                         break;
166                                 }
167                         case KX_SOUNDACT_PLAYSTOP:
168                         case KX_SOUNDACT_PLAYEND:
169                                 {
170                                         m_soundObject->SetLoopMode(SND_LOOP_OFF);
171                                         m_soundScene->AddActiveObject(m_soundObject, curtime);
172                                         m_isplaying = true;
173                                         result = true;
174                                         break;
175                                 }
176                         default:
177                                 // implement me !!
178                                 break;
179                         }
180                 }
181         }
182
183         if (m_isplaying)
184         {
185                 m_soundObject->SetPosition(((KX_GameObject*)this->GetParent())->NodeGetWorldPosition());
186                 m_soundObject->SetVelocity(((KX_GameObject*)this->GetParent())->GetLinearVelocity());
187                 m_soundObject->SetOrientation(((KX_GameObject*)this->GetParent())->NodeGetWorldOrientation());
188                 result = true;
189         }
190         else
191         {
192                 result = false;
193         }
194
195         if (result && (m_soundObject->IsLifeSpanOver(curtime)) && ((m_type == KX_SOUNDACT_PLAYEND) || (m_type == KX_SOUNDACT_PLAYSTOP)))
196         {
197                 m_pino = true;
198         }
199
200         return result;
201 }
202
203
204
205 void KX_SoundActuator::setSoundObject(class SND_SoundObject* soundobject)
206 {
207         m_soundObject = soundobject;
208 }
209
210
211
212 /* ------------------------------------------------------------------------- */
213 /* Python functions                                                          */
214 /* ------------------------------------------------------------------------- */
215
216
217
218 /* Integration hooks ------------------------------------------------------- */
219 PyTypeObject KX_SoundActuator::Type = {
220         PyObject_HEAD_INIT(&PyType_Type)
221                 0,
222                 "KX_SoundActuator",
223                 sizeof(KX_SoundActuator),
224                 0,
225                 PyDestructor,
226                 0,
227                 __getattr,
228                 __setattr,
229                 0, //&MyPyCompare,
230                 __repr,
231                 0, //&cvalue_as_number,
232                 0,
233                 0,
234                 0,
235                 0
236 };
237
238
239
240 PyParentObject KX_SoundActuator::Parents[] = {
241         &KX_SoundActuator::Type,
242                 &SCA_IActuator::Type,
243                 &SCA_ILogicBrick::Type,
244                 &CValue::Type,
245                 NULL
246 };
247
248
249
250 PyMethodDef KX_SoundActuator::Methods[] = {
251         {"setFilename", (PyCFunction) KX_SoundActuator::sPySetFilename, METH_VARARGS,NULL},
252         {"getFilename", (PyCFunction) KX_SoundActuator::sPyGetFilename, METH_VARARGS,NULL},
253         {"startSound",(PyCFunction) KX_SoundActuator::sPyStartSound,METH_VARARGS,NULL},
254         {"pauseSound",(PyCFunction) KX_SoundActuator::sPyPauseSound,METH_VARARGS,NULL},
255         {"stopSound",(PyCFunction) KX_SoundActuator::sPyStopSound,METH_VARARGS,NULL},
256         {"setGain",(PyCFunction) KX_SoundActuator::sPySetGain,METH_VARARGS,NULL},
257         {"getGain",(PyCFunction) KX_SoundActuator::sPyGetGain,METH_VARARGS,NULL},
258         {"setPitch",(PyCFunction) KX_SoundActuator::sPySetPitch,METH_VARARGS,NULL},
259         {"getPitch",(PyCFunction) KX_SoundActuator::sPyGetPitch,METH_VARARGS,NULL},
260         {"setRollOffFactor",(PyCFunction) KX_SoundActuator::sPySetRollOffFactor,METH_VARARGS,NULL},
261         {"getRollOffFactor",(PyCFunction) KX_SoundActuator::sPyGetRollOffFactor,METH_VARARGS,NULL},
262         {"setLooping",(PyCFunction) KX_SoundActuator::sPySetLooping,METH_VARARGS,NULL},
263         {"getLooping",(PyCFunction) KX_SoundActuator::sPyGetLooping,METH_VARARGS,NULL},
264         {"setPosition",(PyCFunction) KX_SoundActuator::sPySetPosition,METH_VARARGS,NULL},
265         {"setVelocity",(PyCFunction) KX_SoundActuator::sPySetVelocity,METH_VARARGS,NULL},
266         {"setOrientation",(PyCFunction) KX_SoundActuator::sPySetOrientation,METH_VARARGS,NULL},
267         {"setType",(PyCFunction) KX_SoundActuator::sPySetType,METH_VARARGS,NULL},
268         {"getType",(PyCFunction) KX_SoundActuator::sPyGetType,METH_VARARGS,NULL},
269         {NULL,NULL,NULL,NULL} //Sentinel
270 };
271
272
273
274 PyObject* KX_SoundActuator::_getattr(const STR_String& attr)
275 {
276         _getattr_up(SCA_IActuator);
277 }
278
279
280
281 PyObject* KX_SoundActuator::PySetFilename(PyObject* self, PyObject* args, PyObject* kwds)
282 {
283         char *soundName = NULL;
284         // void *soundPointer = NULL; /*unused*/
285         
286         if (!PyArg_ParseTuple(args, "s", &soundName))
287                 return NULL;
288
289         Py_Return;
290 }
291
292
293
294 PyObject* KX_SoundActuator::PyGetFilename(PyObject* self, PyObject* args, PyObject* kwds)
295 {
296         if (!m_soundObject)
297         {
298                 return PyString_FromString("");
299         }
300         STR_String objectname = m_soundObject->GetObjectName();
301         char* name = objectname.Ptr();
302         
303         if (!name) {
304                 PyErr_SetString(PyExc_RuntimeError, "Unable to get sound filename");
305                 return NULL;
306         } else
307                 return PyString_FromString(name);
308 }
309
310
311
312 PyObject* KX_SoundActuator::PyStartSound(PyObject* self, PyObject* args, PyObject* kwds)
313 {
314         if (m_soundObject)
315                 m_soundObject->StartSound();    
316         Py_Return;
317 }         
318
319
320
321 PyObject* KX_SoundActuator::PyPauseSound(PyObject* self, PyObject* args, PyObject* kwds)
322 {
323         if (m_soundObject)
324                 m_soundObject->PauseSound();    
325         Py_Return;
326
327
328
329
330 PyObject* KX_SoundActuator::PyStopSound(PyObject* self, PyObject* args, PyObject* kwds)
331 {
332         if (m_soundObject)
333                 m_soundObject->StopSound();     
334         Py_Return;
335 }
336
337
338
339 PyObject* KX_SoundActuator::PySetGain(PyObject* self, PyObject* args, PyObject* kwds)
340 {
341         float gain = 1.0;
342         if (!PyArg_ParseTuple(args, "f", &gain))
343                 return NULL;
344         
345         if (m_soundObject)
346                 m_soundObject->SetGain(gain);
347         
348         Py_Return;
349 }         
350
351
352
353 PyObject* KX_SoundActuator::PyGetGain(PyObject* self, PyObject* args, PyObject* kwds)
354 {
355         float gain = (m_soundObject) ? m_soundObject->GetGain() : 1.0f;
356         PyObject* result = PyFloat_FromDouble(gain);
357         
358         return result;
359 }
360
361
362
363 PyObject* KX_SoundActuator::PySetPitch(PyObject* self, PyObject* args, PyObject* kwds)
364 {
365         float pitch = 1.0;
366         if (!PyArg_ParseTuple(args, "f", &pitch))
367                 return NULL;
368         
369         if (m_soundObject)
370                 m_soundObject->SetPitch(pitch);
371         
372         Py_Return;
373 }         
374
375
376
377 PyObject* KX_SoundActuator::PyGetPitch(PyObject* self, PyObject* args, PyObject* kwds)
378 {
379         float pitch = (m_soundObject) ? m_soundObject->GetPitch() : 1.0;
380         PyObject* result = PyFloat_FromDouble(pitch);
381         
382         return result;
383 }
384
385
386
387 PyObject* KX_SoundActuator::PySetRollOffFactor(PyObject* self, PyObject* args, PyObject* kwds)
388 {
389         float rollofffactor = 1.0;
390         if (!PyArg_ParseTuple(args, "f", &rollofffactor))
391                 return NULL;
392         
393         if (m_soundObject)
394                 m_soundObject->SetRollOffFactor(rollofffactor);
395
396         Py_Return;
397 }         
398
399
400
401 PyObject* KX_SoundActuator::PyGetRollOffFactor(PyObject* self, PyObject* args, PyObject* kwds)
402 {
403         float rollofffactor = (m_soundObject) ? m_soundObject->GetRollOffFactor() : 1.0;
404         PyObject* result = PyFloat_FromDouble(rollofffactor);
405         
406         return result;
407 }
408
409
410
411 PyObject* KX_SoundActuator::PySetLooping(PyObject* self, PyObject* args, PyObject* kwds)
412 {
413         bool looping = 1;
414         if (!PyArg_ParseTuple(args, "i", &looping))
415                 return NULL;
416         
417         if (m_soundObject)
418                 m_soundObject->SetLoopMode(looping);
419         
420         Py_Return;
421 }         
422
423
424
425 PyObject* KX_SoundActuator::PyGetLooping(PyObject* self, PyObject* args, PyObject* kwds)
426 {
427         int looping = (m_soundObject) ? m_soundObject->GetLoopMode() : SND_LOOP_OFF;
428         PyObject* result = PyInt_FromLong(looping);
429         
430         return result;
431 }
432
433
434
435 PyObject* KX_SoundActuator::PySetPosition(PyObject* self, PyObject* args, PyObject* kwds)
436 {
437         MT_Point3 pos;
438         pos[0] = 0.0;
439         pos[1] = 0.0;
440         pos[2] = 0.0;
441
442         if (!PyArg_ParseTuple(args, "fff", &pos[0], &pos[1], &pos[2]))
443                 return NULL;
444         
445         if (m_soundObject)
446                 m_soundObject->SetPosition(pos);
447         
448         Py_Return;
449 }         
450
451
452
453 PyObject* KX_SoundActuator::PySetVelocity(PyObject* self, PyObject* args, PyObject* kwds)
454 {
455         MT_Vector3 vel;
456         vel[0] = 0.0;
457         vel[1] = 0.0;
458         vel[2] = 0.0;
459
460         if (!PyArg_ParseTuple(args, "fff", &vel[0], &vel[1], &vel[2]))
461                 return NULL;
462         
463         if (m_soundObject)
464                 m_soundObject->SetVelocity(vel);
465         
466         Py_Return;
467 }         
468
469
470
471 PyObject* KX_SoundActuator::PySetOrientation(PyObject* self, PyObject* args, PyObject* kwds)
472 {
473         MT_Matrix3x3 ori;
474         ori[0][0] = 1.0;
475         ori[0][1] = 0.0;
476         ori[0][2] = 0.0;
477         ori[1][0] = 0.0;
478         ori[1][1] = 1.0;
479         ori[1][2] = 0.0;
480         ori[2][0] = 0.0;
481         ori[2][1] = 0.0;
482         ori[2][2] = 1.0;
483
484         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]))
485                 return NULL;
486         
487         if (m_soundObject)
488                 m_soundObject->SetOrientation(ori);
489         
490         Py_Return;
491 }
492
493 PyObject* KX_SoundActuator::PySetType(PyObject* self, PyObject* args, PyObject* kwds)
494 {
495         int typeArg;
496
497         if (!PyArg_ParseTuple(args, "i", &typeArg)) {
498                 return NULL;
499         }
500
501         if ( (typeArg > KX_SOUNDACT_NODEF)
502           && (typeArg < KX_SOUNDACT_MAX) ) {
503                 m_type = (KX_SOUNDACT_TYPE) typeArg;
504         }
505
506         Py_Return;
507 }
508
509 PyObject* KX_SoundActuator::PyGetType(PyObject* self, PyObject* args, PyObject* kwds)
510 {
511         return PyInt_FromLong(m_type);
512 }
513
514
515