/* * $Id$ * * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. The Blender * Foundation also sells licenses for use in proprietary software under * the Blender License. See http://www.blender.org/BL/ for information * about this. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. * * This is a new part of Blender. * * Contributor(s): Chris Keith * * ***** END GPL/BL DUAL LICENSE BLOCK ***** */ #include #include #include #include #include #include #include /* allqueue() */ #include "mydevice.h" /* redraw defines */ #include "gen_utils.h" #include "Sound.h" /*****************************************************************************/ /* Python BPy_Sound defaults: */ /*****************************************************************************/ /*****************************************************************************/ /* Python API function prototypes for the Sound module. */ /*****************************************************************************/ static PyObject *M_Sound_New (PyObject *self, PyObject *args, PyObject *keywords); static PyObject *M_Sound_Get (PyObject *self, PyObject *args); static PyObject *M_Sound_Load (PyObject *self, PyObject *args); /************************************************************************/ /* The following string definitions are used for documentation strings. */ /* In Python these will be written to the console when doing a */ /* Blender.Sound.__doc__ */ /************************************************************************/ static char M_Sound_doc[] = "The Blender Sound module\n\n"; static char M_Sound_New_doc[] = "() - return a new Sound object -- unimplemented"; static char M_Sound_Get_doc[] = "(name) - return the sound with the name 'name', \ returns None if not found.\n If 'name' is not specified, \ it returns a list of all sounds in the\ncurrent scene."; static char M_Sound_Load_doc[] = "(filename, redraw = 0) - return sound from file filename as Sound Object,\n\ returns None if not found."; /*****************************************************************************/ /* Python method structure definition for Blender.Sound module: */ /*****************************************************************************/ struct PyMethodDef M_Sound_methods[] = { {"New",(PyCFunction)M_Sound_New, METH_VARARGS|METH_KEYWORDS, M_Sound_New_doc}, {"Get", M_Sound_Get, METH_VARARGS, M_Sound_Get_doc}, {"get", M_Sound_Get, METH_VARARGS, M_Sound_Get_doc}, {"Load", M_Sound_Load, METH_VARARGS, M_Sound_Load_doc}, {NULL, NULL, 0, NULL} }; /*****************************************************************************/ /* Python Sound_Type callback function prototypes: */ /*****************************************************************************/ static void Sound_dealloc (BPy_Sound *self); static int Sound_setAttr (BPy_Sound *self, char *name, PyObject *v); static int Sound_compare (BPy_Sound *a, BPy_Sound *b); static PyObject *Sound_getAttr (BPy_Sound *self, char *name); static PyObject *Sound_repr (BPy_Sound *self); #define SOUND_FLOAT_METHODS(funcname, varname) \ static PyObject *Sound_get ## funcname(BPy_Sound *self) { \ char e[256]; \ PyObject *attr = PyFloat_FromDouble(self->sound->varname); \ if (attr) return attr; \ sprintf(e, "couldn't get Sound.%s attribute", #varname); \ return EXPP_ReturnPyObjError (PyExc_RuntimeError, e); \ } \ static PyObject *Sound_set ## funcname(BPy_Sound *self, PyObject *args) { \ float f = 0; \ if (!PyArg_ParseTuple(args, "f", &f)) \ return (EXPP_ReturnPyObjError (PyExc_TypeError, \ "expected float argument")); \ self->sound->varname = f; \ Py_INCREF(Py_None); \ return Py_None; \ } #define SOUND_FLOAT_METHOD_FUNCS(varname) \ {"get"#varname, (PyCFunction)Sound_get ## varname, METH_NOARGS, \ "() - Return Sound object "#varname}, \ {"set"#varname, (PyCFunction)Sound_set ## varname, METH_VARARGS, \ "(float) - Change Sound object "#varname}, /*****************************************************************************/ /* Python BPy_Sound methods declarations: */ /*****************************************************************************/ static PyObject *Sound_getName(BPy_Sound *self); static PyObject *Sound_getFilename(BPy_Sound *self); static PyObject *Sound_play(BPy_Sound *self); static PyObject *Sound_makeActive(BPy_Sound *self); SOUND_FLOAT_METHODS(Volume, volume) SOUND_FLOAT_METHODS(Panning, panning) SOUND_FLOAT_METHODS(Attenuation, attenuation) SOUND_FLOAT_METHODS(Pitch, pitch) SOUND_FLOAT_METHODS(MinGain, min_gain) SOUND_FLOAT_METHODS(MaxGain, max_gain) SOUND_FLOAT_METHODS(Distance, distance) /*****************************************************************************/ /* Python BPy_Sound methods table: */ /*****************************************************************************/ static PyMethodDef BPy_Sound_methods[] = { /* name, method, flags, doc */ {"getName", (PyCFunction)Sound_getName, METH_NOARGS, "() - Return Sound object name"}, {"getFilename", (PyCFunction)Sound_getFilename, METH_NOARGS, "() - Return Sound object filename"}, {"play", (PyCFunction)Sound_play, METH_NOARGS, "() - play this sound"}, {"makeActive", (PyCFunction)Sound_makeActive, METH_NOARGS, "() - make this the active sound in the sound buttons win (also redraws)"}, SOUND_FLOAT_METHOD_FUNCS(Volume) SOUND_FLOAT_METHOD_FUNCS(Panning) SOUND_FLOAT_METHOD_FUNCS(Attenuation) SOUND_FLOAT_METHOD_FUNCS(Pitch) SOUND_FLOAT_METHOD_FUNCS(MinGain) SOUND_FLOAT_METHOD_FUNCS(MaxGain) SOUND_FLOAT_METHOD_FUNCS(Distance) {NULL, NULL, 0, NULL} }; /*****************************************************************************/ /* Python Sound_Type structure definition: */ /*****************************************************************************/ PyTypeObject Sound_Type = { PyObject_HEAD_INIT(NULL) 0, /* ob_size */ "Blender Sound", /* tp_name */ sizeof (BPy_Sound), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ (destructor)Sound_dealloc, /* tp_dealloc */ 0, /* tp_print */ (getattrfunc)Sound_getAttr, /* tp_getattr */ (setattrfunc)Sound_setAttr, /* tp_setattr */ (cmpfunc)Sound_compare, /* tp_compare */ (reprfunc)Sound_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_as_hash */ 0,0,0,0,0,0, 0, /* tp_doc */ 0,0,0,0,0,0, BPy_Sound_methods, /* tp_methods */ 0, /* tp_members */ }; /*****************************************************************************/ /* Function: M_Sound_New */ /* Python equivalent: Blender.Sound.New */ /*****************************************************************************/ static PyObject *M_Sound_New(PyObject *self, PyObject *args, PyObject *keywords) { printf ("In Sound_New() - unimplemented in 2.34\n"); Py_INCREF(Py_None); return Py_None; } /* NOTE: these were copied and modified from image.h. To Be Done TBD: * macro-ize them, or C++ templates eventually? */ /********************************************************************************/ /* Function: M_Sound_Get */ /* Python equivalent: Blender.Sound.Get */ /* Description: Receives a string and returns the Sound object */ /* whose name matches the string. If no argument is */ /* passed in, a list of all Sound names in the */ /* current scene is returned. */ /*********************************************************************************/ static PyObject *M_Sound_Get(PyObject *self, PyObject *args) { char *name = NULL; bSound *snd_iter; if (!PyArg_ParseTuple(args, "|s", &name)) return (EXPP_ReturnPyObjError (PyExc_TypeError, "expected string argument (or nothing)")); snd_iter = G.main->sound.first; if (name) { /* (name) - Search Sound by name */ BPy_Sound *wanted_Sound = NULL; while ((snd_iter) && (wanted_Sound == NULL)) { if (strcmp (name, snd_iter->id.name+2) == 0) { wanted_Sound = (BPy_Sound *)PyObject_NEW(BPy_Sound, &Sound_Type); if (wanted_Sound) { wanted_Sound->sound = snd_iter; break; } } snd_iter = snd_iter->id.next; } if (wanted_Sound == NULL) { /* Requested Sound doesn't exist */ char error_msg[64]; PyOS_snprintf(error_msg, sizeof(error_msg), "Sound \"%s\" not found", name); return (EXPP_ReturnPyObjError (PyExc_NameError, error_msg)); } return (PyObject *)wanted_Sound; } else { /* () - return a list of all Sounds in the scene */ int index = 0; PyObject *snd_list, *pyobj; snd_list = PyList_New (BLI_countlist (&(G.main->sound))); if (snd_list == NULL) return (EXPP_ReturnPyObjError (PyExc_MemoryError, "couldn't create PyList")); while (snd_iter) { pyobj = Sound_CreatePyObject (snd_iter); if (!pyobj) return (EXPP_ReturnPyObjError (PyExc_MemoryError, "couldn't create PyObject")); PyList_SET_ITEM (snd_list, index, pyobj); snd_iter = snd_iter->id.next; index++; } return (snd_list); } } /*****************************************************************************/ /* Function: M_Sound_Load */ /* Python equivalent: Blender.Sound.Load */ /* Description: Receives a string and returns the Sound object */ /* whose filename matches the string. */ /*****************************************************************************/ static PyObject *M_Sound_Load(PyObject *self, PyObject *args) { char *fname; bSound *snd_ptr; BPy_Sound *snd; if (!PyArg_ParseTuple(args, "s", &fname)) return (EXPP_ReturnPyObjError (PyExc_TypeError, "expected string argument")); snd = (BPy_Sound *)PyObject_NEW(BPy_Sound, &Sound_Type); if (!snd) return (EXPP_ReturnPyObjError (PyExc_MemoryError, "couldn't create PyObject Sound_Type")); snd_ptr = sound_new_sound(fname); if (snd_ptr) { if (G.ssound) { G.ssound->sound= snd_ptr; } } if (!snd_ptr) return (EXPP_ReturnPyObjError (PyExc_IOError, "not a valid sound sample")); snd->sound = snd_ptr; return (PyObject *)snd; } /*****************************************************************************/ /* Function: Sound_Init */ /*****************************************************************************/ PyObject *Sound_Init (void) { PyObject *submodule; Sound_Type.ob_type = &PyType_Type; submodule = Py_InitModule3("Blender.Sound", M_Sound_methods, M_Sound_doc); return (submodule); } /************************/ /*** The Sound PyType ***/ /************************/ /*****************************************************************************/ /* Function: Sound_dealloc */ /* Description: This is a callback function for the BPy_Sound type. It is */ /* the destructor function. */ /*****************************************************************************/ static void Sound_dealloc (BPy_Sound *self) { PyObject_DEL (self); } /*****************************************************************************/ /* Function: Sound_CreatePyObject */ /* Description: This function will create a new BPy_Sound from an existing */ /* Blender Sound structure. */ /*****************************************************************************/ PyObject *Sound_CreatePyObject (bSound *snd) { BPy_Sound *py_snd; py_snd = (BPy_Sound *)PyObject_NEW (BPy_Sound, &Sound_Type); if (!py_snd) return EXPP_ReturnPyObjError (PyExc_MemoryError, "couldn't create BPy_Sound object"); py_snd->sound = snd; return (PyObject *)py_snd; } /*****************************************************************************/ /* Function: Sound_CheckPyObject */ /* Description: This function returns true when the given PyObject is of the */ /* type Sound. Otherwise it will return false. */ /*****************************************************************************/ int Sound_CheckPyObject (PyObject *pyobj) { return (pyobj->ob_type == &Sound_Type); } /*****************************************************************************/ /* Function: Sound_FromPyObject */ /* Description: Returns the Blender Sound associated with this object */ /*****************************************************************************/ bSound *Sound_FromPyObject (PyObject *pyobj) { return ((BPy_Sound *)pyobj)->sound; } /*****************************************************************************/ /* Python BPy_Sound methods: */ /*****************************************************************************/ static PyObject *Sound_getName(BPy_Sound *self) { PyObject *attr = PyString_FromString(self->sound->id.name+2); if (attr) return attr; return (EXPP_ReturnPyObjError (PyExc_RuntimeError, "couldn't get Sound.name attribute")); } static PyObject *Sound_getFilename(BPy_Sound *self) { PyObject *attr = PyString_FromString(self->sound->name); if (attr) return attr; return (EXPP_ReturnPyObjError (PyExc_RuntimeError, "couldn't get Sound.filename attribute")); } static PyObject *Sound_play(BPy_Sound *self) { sound_play_sound(self->sound); Py_INCREF(Py_None); return Py_None; } static PyObject *Sound_makeActive(BPy_Sound *self) { bSound *snd_ptr = self->sound; if (snd_ptr) { if (G.ssound) { G.ssound->sound = snd_ptr; } } allqueue(REDRAWSOUND, 0); allqueue(REDRAWBUTSLOGIC, 0); Py_INCREF (Py_None); return Py_None; } /*****************************************************************************/ /* Function: Sound_getAttr */ /* Description: This is a callback function for the BPy_Sound type. It is */ /* the function that accesses BPy_Sound member variables and */ /* methods. */ /*****************************************************************************/ static PyObject *Sound_getAttr (BPy_Sound *self, char *name) { PyObject *attr = Py_None; if (strcmp(name, "name") == 0) attr = PyString_FromString(self->sound->id.name+2); else if (strcmp(name, "filename") == 0) attr = PyString_FromString(self->sound->name); else if (strcmp(name, "__members__") == 0) attr = Py_BuildValue("[s,s]", "name", "filename"); if (!attr) return (EXPP_ReturnPyObjError (PyExc_MemoryError, "couldn't create PyObject")); if (attr != Py_None) return attr; /* attribute found, return its value */ /* not an attribute, search the methods table */ return Py_FindMethod(BPy_Sound_methods, (PyObject *)self, name); } /*****************************************************************************/ /* Function: Sound_setAttr */ /* Description: This is a callback function for the BPy_Sound type. It is the*/ /* function that changes Sound object members values. If this */ /* data is linked to a Blender Sound, it also gets updated. */ /*****************************************************************************/ static int Sound_setAttr (BPy_Sound *self, char *name, PyObject *value) { PyObject *valtuple; PyObject *error = NULL; /* We're playing a trick on the Python API users here. Even if they use * Sound.member = val instead of Sound.setMember(value), we end up using the * function anyway, since it already has error checking, clamps to the right * interval and updates the Blender Sound structure when necessary. */ valtuple = Py_BuildValue("(O)", value); /*the set* functions expect a tuple*/ if (!valtuple) return EXPP_ReturnIntError(PyExc_MemoryError, "SoundSetAttr: couldn't create PyTuple"); /* if (strcmp (name, "name") == 0) error = Sound_setName (self, valtuple); else */ { /* Error: no such member in the Sound object structure */ Py_DECREF(value); Py_DECREF(valtuple); return (EXPP_ReturnIntError (PyExc_KeyError, "attribute not found or immutable")); } Py_DECREF(valtuple); if (error != Py_None) return -1; Py_DECREF(Py_None); /* incref'ed by the called set* function */ return 0; /* normal exit */ } /*****************************************************************************/ /* Function: Sound_compare */ /* Description: This is a callback function for the BPy_Sound type. It */ /* compares two Sound_Type objects. Only the "==" and "!=" */ /* comparisons are meaninful. Returns 0 for equality and -1 if */ /* they don't point to the same Blender Sound struct. */ /* In Python it becomes 1 if they are equal, 0 otherwise. */ /*****************************************************************************/ static int Sound_compare (BPy_Sound *a, BPy_Sound *b) { bSound *pa = a->sound, *pb = b->sound; return (pa == pb) ? 0:-1; } /*****************************************************************************/ /* Function: Sound_repr */ /* Description: This is a callback function for the BPy_Sound type. It */ /* builds a meaninful string to represent Sound objects. */ /*****************************************************************************/ static PyObject *Sound_repr (BPy_Sound *self) { return PyString_FromFormat("[Sound \"%s\"]", self->sound->id.name+2); }