Browse code

- copied from pysip branch.

- py_sems is aimed at integrating as much functionnalities
from the core as possible into python driven applications
(not necessarily IVRs), in a more easy way. The classes can
then just be used as in C++.

- this plug-in uses the sip4 package included in debian.
Please refer to http://www.riverbankcomputing.co.uk/sip/
for more informations on the binding generator.
Please note that you do not need it, if you just want to compile
SEMS. You will need it first if you want to generate more classes.



git-svn-id: http://svn.berlios.de/svnroot/repos/sems/trunk@220 8eb893ce-cfd4-0310-b710-fb5ebe64c474

Raphael Coeffic authored on 09/02/2007 09:37:29
Showing 35 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,598 @@
1
+/*
2
+ * $Id: Ivr.cpp,v 1.26.2.1 2005/09/02 13:47:46 rco Exp $
3
+ * Copyright (C) 2002-2003 Fhg Fokus
4
+ *
5
+ * This file is part of sems, a free SIP media server.
6
+ *
7
+ * This program is free software; you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation; either version 2 of the License, or
10
+ * (at your option) any later version
11
+ *
12
+ * This program is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
+ * GNU General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU General Public License
18
+ * along with this program; if not, write to the Free Software
19
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20
+ */
21
+
22
+//#include "IvrDialogBase.h"
23
+//#include "IvrSipDialog.h"
24
+#include "IvrAudio.h"
25
+#include "Ivr.h"
26
+
27
+#include "AmConfigReader.h"
28
+#include "AmConfig.h"
29
+#include "log.h"
30
+#include "AmApi.h"
31
+#include "AmUtils.h"
32
+#include "AmSessionScheduler.h"
33
+//#include "AmSessionTimer.h"
34
+#include "AmPlugIn.h"
35
+
36
+#include "sip/sipAPIpy_ivr.h"
37
+#include "sip/sippy_ivrIvrDialog.h"
38
+
39
+#include <unistd.h>
40
+#include <pthread.h>
41
+#include <regex.h>
42
+#include <dirent.h>
43
+
44
+#include <set>
45
+using std::set;
46
+
47
+
48
+#define PYFILE_REGEX "(.+)\\.(py|pyc|pyo)$"
49
+
50
+
51
+EXPORT_SESSION_FACTORY(IvrFactory,MOD_NAME);
52
+
53
+PyMODINIT_FUNC initpy_ivr();
54
+
55
+struct PythonGIL
56
+{
57
+    PyGILState_STATE gst;
58
+
59
+    PythonGIL() { gst = PyGILState_Ensure(); }
60
+    ~PythonGIL(){ PyGILState_Release(gst);   }
61
+};
62
+
63
+
64
+// This must be the first declaration of every 
65
+// function using Python C-API.
66
+// But this is not necessary in function which
67
+// will get called from Python
68
+#define PYLOCK PythonGIL _py_gil
69
+
70
+extern "C" {
71
+
72
+    static PyObject* ivr_log(PyObject*, PyObject* args)
73
+    {
74
+	int level;
75
+	char *msg;
76
+
77
+	if(!PyArg_ParseTuple(args,"is",&level,&msg))
78
+	    return NULL;
79
+
80
+	if((level)<=log_level) {
81
+
82
+	    //if(level == L_ERR)
83
+	    //assert(0);
84
+
85
+	    if(log_stderr)
86
+		log_print( level, msg );
87
+	    else {
88
+		switch(level){
89
+		case L_ERR:
90
+		    syslog(LOG_ERR | L_FAC, "Error: %s", msg);
91
+		    break;
92
+		case L_WARN:
93
+		    syslog(LOG_WARNING | L_FAC, "Warning: %s", msg);
94
+		    break;
95
+		case L_INFO:
96
+		    syslog(LOG_INFO | L_FAC, "Info: %s", msg);
97
+		    break;
98
+		case L_DBG:
99
+		    syslog(LOG_DEBUG | L_FAC, "Debug: %s", msg);
100
+		    break;
101
+		}
102
+	    }
103
+	}
104
+	
105
+	Py_INCREF(Py_None);
106
+	return Py_None;
107
+    }
108
+
109
+    static PyObject* ivr_getHeader(PyObject*, PyObject* args)
110
+    {
111
+	char* headers;
112
+	char* header_name;
113
+	if(!PyArg_ParseTuple(args,"ss",&headers,&header_name))
114
+	    return NULL;
115
+
116
+	string res = getHeader(headers,header_name);
117
+	return PyString_FromString(res.c_str());
118
+    }
119
+
120
+
121
+    static PyMethodDef ivr_methods[] = {
122
+ 	{"log", (PyCFunction)ivr_log, METH_VARARGS,"Log a message using Sems' logging system"},
123
+	{"getHeader", (PyCFunction)ivr_getHeader, METH_VARARGS,"Python getHeader wrapper"},
124
+	{NULL}  /* Sentinel */
125
+    };
126
+}
127
+
128
+IvrFactory::IvrFactory(const string& _app_name)
129
+    : AmSessionFactory(_app_name),
130
+      user_timer_fact(NULL)
131
+{
132
+}
133
+
134
+void IvrFactory::setScriptPath(const string& path)
135
+{
136
+    string python_path = script_path = path;
137
+
138
+    
139
+    if(python_path.length()){
140
+
141
+	python_path = AmConfig::PlugInPath + ":" + python_path;
142
+    }
143
+    else
144
+	python_path = AmConfig::PlugInPath;
145
+
146
+    char* old_path=0;
147
+    if((old_path = getenv("PYTHONPATH")) != 0)
148
+	if(strlen(old_path))
149
+	    python_path += ":" + string(old_path);
150
+
151
+    DBG("setting PYTHONPATH to: '%s'\n",python_path.c_str());
152
+    setenv("PYTHONPATH",python_path.c_str(),1);
153
+
154
+}
155
+
156
+void IvrFactory::import_object(PyObject* m, char* name, PyTypeObject* type)
157
+{
158
+    if (PyType_Ready(type) < 0){
159
+	ERROR("PyType_Ready failed !\n");
160
+        return;
161
+    }
162
+    Py_INCREF(type);
163
+    PyModule_AddObject(m, name, (PyObject *)type);
164
+}
165
+
166
+void IvrFactory::import_ivr_builtins()
167
+{
168
+    // ivr module - start
169
+    PyImport_AddModule("ivr");
170
+    ivr_module = Py_InitModule("ivr",ivr_methods);
171
+
172
+    // IvrSipDialog (= AmSipDialog)
173
+    //import_object(ivr_module, "IvrSipDialog", &IvrSipDialogType);
174
+
175
+    // IvrDialogBase
176
+    //import_object(ivr_module,"IvrDialogBase",&IvrDialogBaseType);
177
+
178
+
179
+    // IvrAudioFile
180
+    import_object(ivr_module,"IvrAudioFile",&IvrAudioFileType);
181
+
182
+    PyModule_AddIntConstant(ivr_module, "AUDIO_READ",AUDIO_READ);
183
+    PyModule_AddIntConstant(ivr_module, "AUDIO_WRITE",AUDIO_WRITE);
184
+    // ivr module - end
185
+
186
+    // add log level for the log module
187
+    PyModule_AddIntConstant(ivr_module, "SEMS_LOG_LEVEL",log_level);
188
+
189
+    import_module("log");
190
+    initpy_ivr();
191
+}
192
+
193
+void IvrFactory::import_module(const char* modname)
194
+{
195
+    PyObject* py_mod_name = PyString_FromString(modname);
196
+    PyObject* py_mod = PyImport_Import(py_mod_name);
197
+    Py_DECREF(py_mod_name);
198
+    
199
+    if(!py_mod){
200
+	PyErr_Print();
201
+	ERROR("IvrFactory: could not find python module '%s'.\n",modname);
202
+	ERROR("IvrFactory: please check your installation.\n");
203
+	return;
204
+    }
205
+}
206
+
207
+void IvrFactory::init_python_interpreter()
208
+{
209
+    Py_Initialize();
210
+    PyEval_InitThreads();
211
+    import_ivr_builtins();
212
+    PyEval_ReleaseLock();
213
+}
214
+
215
+IvrDialog* IvrFactory::newDlg(const string& name)
216
+{
217
+    PYLOCK;
218
+
219
+    map<string,IvrScriptDesc>::iterator mod_it = mod_reg.find(name);
220
+    if(mod_it == mod_reg.end()){
221
+	ERROR("Unknown script name '%s'\n", name.c_str());
222
+	throw AmSession::Exception(500,"Unknown Application");
223
+    }
224
+
225
+    IvrScriptDesc& mod_desc = mod_it->second;
226
+
227
+    AmDynInvoke* user_timer = user_timer_fact->getInstance();
228
+    if(!user_timer){
229
+	ERROR("could not get a user timer reference\n");
230
+	throw AmSession::Exception(500,"could not get a user timer reference");
231
+    }
232
+	
233
+    PyObject* dlg_inst = PyObject_Call(mod_desc.dlg_class,PyTuple_New(0),NULL);
234
+    if(!dlg_inst){
235
+	
236
+	PyErr_Print();
237
+	ERROR("IvrFactory: while loading \"%s\": could not create instance\n",
238
+	      name.c_str());
239
+	throw AmSession::Exception(500,"Internal error in IVR plug-in.");
240
+	
241
+	return NULL;
242
+    }
243
+
244
+    int err=0;
245
+    IvrDialog* dlg = (IvrDialog*)sipForceConvertTo_IvrDialog(dlg_inst,&err);
246
+    if(!dlg || err){
247
+	
248
+	PyErr_Print();
249
+	ERROR("IvrFactory: while loading \"%s\": could not retrieve IvrDialog ptr.\n",
250
+	      name.c_str());
251
+	throw AmSession::Exception(500,"Internal error in IVR plug-in.");
252
+	Py_DECREF(dlg_inst);
253
+
254
+	return NULL;
255
+    }
256
+
257
+    // take the ownership over dlg
258
+    sipTransfer(dlg_inst,1);
259
+
260
+    return dlg;
261
+}
262
+
263
+bool IvrFactory::loadScript(const string& path)
264
+{
265
+    PYLOCK;
266
+    
267
+    PyObject *modName,*mod,*dict, *dlg_class, *config=NULL;
268
+
269
+    modName = PyString_FromString(path.c_str());
270
+    mod     = PyImport_Import(modName);
271
+
272
+    AmConfigReader cfg;
273
+    string cfg_file = add2path(AmConfig::ModConfigPath,1,(path + ".conf").c_str());
274
+
275
+    Py_DECREF(modName);
276
+
277
+    if(!mod){
278
+        PyErr_Print();
279
+        WARN("IvrFactory: Failed to load \"%s\"\n", path.c_str());
280
+
281
+	dict = PyImport_GetModuleDict();
282
+	Py_INCREF(dict);
283
+	PyDict_DelItemString(dict,path.c_str());
284
+	Py_DECREF(dict);
285
+
286
+	return false;
287
+    }
288
+
289
+    dict = PyModule_GetDict(mod);
290
+    dlg_class = PyDict_GetItemString(dict, "IvrScript");
291
+
292
+    if(!dlg_class){
293
+
294
+	PyErr_Print();
295
+	WARN("IvrFactory: class IvrDialog not found in \"%s\"\n", path.c_str());
296
+	goto error1;
297
+    }
298
+
299
+    Py_INCREF(dlg_class);
300
+
301
+    if(!PyObject_IsSubclass(dlg_class,(PyObject *)sipClass_IvrDialog)){
302
+
303
+	WARN("IvrFactory: in \"%s\": IvrScript is not a "
304
+	     "subtype of IvrDialog\n", path.c_str());
305
+
306
+	goto error2;
307
+    }
308
+
309
+    if(cfg.loadFile(cfg_file)){
310
+	ERROR("could not load config file at %s\n",cfg_file.c_str());
311
+	goto error2;
312
+    }
313
+
314
+    config = PyDict_New();
315
+    if(!config){
316
+	ERROR("could not allocate new dict for config\n");
317
+	goto error2;
318
+    }
319
+
320
+    for(map<string,string>::const_iterator it = cfg.begin();
321
+	it != cfg.end(); it++){
322
+	
323
+	PyDict_SetItem(config, 
324
+		       PyString_FromString(it->first.c_str()),
325
+		       PyString_FromString(it->second.c_str()));
326
+    }
327
+
328
+    PyObject_SetAttrString(mod,"config",config);
329
+
330
+    mod_reg.insert(make_pair(path,
331
+			     IvrScriptDesc(mod,dlg_class)));
332
+
333
+    return true;
334
+
335
+ error2:
336
+    Py_DECREF(dlg_class);
337
+ error1:
338
+    Py_DECREF(mod);
339
+
340
+    return false;
341
+}
342
+
343
+/**
344
+ * Loads python script path and default script file from configuration file
345
+ */
346
+int IvrFactory::onLoad()
347
+{
348
+    user_timer_fact = AmPlugIn::instance()->getFactory4Di("user_timer");
349
+    if(!user_timer_fact){
350
+	
351
+	ERROR("could not load user_timer from session_timer plug-in\n");
352
+	return -1;
353
+    }
354
+
355
+
356
+    AmConfigReader cfg;
357
+
358
+    if(cfg.loadFile(add2path(AmConfig::ModConfigPath,1,MOD_NAME ".conf")))
359
+	return -1;
360
+
361
+    // get application specific global parameters
362
+    configureModule(cfg);
363
+
364
+    setScriptPath(cfg.getParameter("script_path"));
365
+    init_python_interpreter();
366
+
367
+    DBG("** IVR compile time configuration:\n");
368
+    DBG("**     built with PYTHON support.\n");
369
+
370
+#ifdef IVR_WITH_TTS
371
+    DBG("**     Text-To-Speech enabled\n");
372
+#else
373
+    DBG("**     Text-To-Speech disabled\n");
374
+#endif
375
+
376
+    DBG("** IVR run time configuration:\n");
377
+    DBG("**     script path:         \'%s\'\n", script_path.c_str());
378
+
379
+    regex_t reg;
380
+    if(regcomp(&reg,PYFILE_REGEX,REG_EXTENDED)){
381
+	ERROR("while compiling regular expression\n");
382
+	return -1;
383
+    }
384
+
385
+    DIR* dir = opendir(script_path.c_str());
386
+    if(!dir){
387
+	regfree(&reg);
388
+	ERROR("Ivr: script pre-loader (%s): %s\n",
389
+	      script_path.c_str(),strerror(errno));
390
+	return -1;
391
+    }
392
+
393
+    DBG("directory '%s' opened\n",script_path.c_str());
394
+
395
+    set<string> unique_entries;
396
+    regmatch_t  pmatch[2];
397
+
398
+    struct dirent* entry=0;
399
+    while((entry = readdir(dir)) != NULL){
400
+
401
+	if(!regexec(&reg,entry->d_name,2,pmatch,0)){
402
+
403
+	    string name(entry->d_name + pmatch[1].rm_so,
404
+			pmatch[1].rm_eo - pmatch[1].rm_so);
405
+
406
+	    unique_entries.insert(name);
407
+	}
408
+    }
409
+    closedir(dir);
410
+    regfree(&reg);
411
+
412
+    AmPlugIn* plugin = AmPlugIn::instance();
413
+    for(set<string>::iterator it = unique_entries.begin();
414
+	it != unique_entries.end(); it++) {
415
+
416
+	if(loadScript(*it)){
417
+	    bool res = plugin->registerFactory4App(*it,this);
418
+	    if(res)
419
+		INFO("Application script registered: %s.\n",
420
+		     it->c_str());
421
+	}
422
+    }
423
+
424
+    return 0; // don't stop sems from starting up
425
+}
426
+
427
+/**
428
+ * Load a script using user name from URI.
429
+ * Note: there is no default script.
430
+ */
431
+AmSession* IvrFactory::onInvite(const AmSipRequest& req)
432
+{
433
+    if(req.cmd != MOD_NAME)
434
+	return newDlg(req.cmd);
435
+    else
436
+	return newDlg(req.user);
437
+}
438
+
439
+IvrDialog::IvrDialog()
440
+    : py_mod(NULL),
441
+      py_dlg(NULL),
442
+      playlist(this),
443
+      user_timer(NULL)
444
+{
445
+    sip_relay_only = false;
446
+}
447
+
448
+IvrDialog::IvrDialog(AmDynInvoke* user_timer)
449
+    : py_mod(NULL), 
450
+      py_dlg(NULL),
451
+      playlist(this),
452
+      user_timer(user_timer)
453
+{
454
+    sip_relay_only = false;
455
+}
456
+
457
+IvrDialog::~IvrDialog()
458
+{
459
+    DBG("IvrDialog::~IvrDialog()\n");
460
+
461
+    PYLOCK;
462
+    Py_XDECREF(py_mod);
463
+    Py_XDECREF(py_dlg);
464
+}
465
+
466
+void IvrDialog::setPyPtrs(PyObject *mod, PyObject *dlg)
467
+{
468
+    assert(py_mod = mod);
469
+    assert(py_dlg = dlg);
470
+    Py_INCREF(py_mod);
471
+    Py_INCREF(py_dlg);
472
+}
473
+
474
+static PyObject *
475
+type_error(const char *msg)
476
+{
477
+        PyErr_SetString(PyExc_TypeError, msg);
478
+        return NULL;
479
+}
480
+
481
+static PyObject *
482
+null_error(void)
483
+{
484
+        if (!PyErr_Occurred())
485
+                PyErr_SetString(PyExc_SystemError,
486
+                                "null argument to internal routine");
487
+        return NULL;
488
+}
489
+
490
+PyObject *
491
+PyObject_VaCallMethod(PyObject *o, char *name, char *format, va_list va)
492
+{
493
+        PyObject *args, *func = 0, *retval;
494
+
495
+        if (o == NULL || name == NULL)
496
+                return null_error();
497
+
498
+        func = PyObject_GetAttrString(o, name);
499
+        if (func == NULL) {
500
+                PyErr_SetString(PyExc_AttributeError, name);
501
+                return 0;
502
+        }
503
+
504
+        if (!PyCallable_Check(func))
505
+                return type_error("call of non-callable attribute");
506
+
507
+        if (format && *format) {
508
+                args = Py_VaBuildValue(format, va);
509
+        }
510
+        else
511
+                args = PyTuple_New(0);
512
+
513
+        if (!args)
514
+                return NULL;
515
+
516
+        if (!PyTuple_Check(args)) {
517
+                PyObject *a;
518
+
519
+                a = PyTuple_New(1);
520
+                if (a == NULL)
521
+                        return NULL;
522
+                if (PyTuple_SetItem(a, 0, args) < 0)
523
+                        return NULL;
524
+                args = a;
525
+        }
526
+
527
+        retval = PyObject_Call(func, args, NULL);
528
+
529
+        Py_DECREF(args);
530
+        Py_DECREF(func);
531
+
532
+        return retval;
533
+}
534
+
535
+bool IvrDialog::callPyEventHandler(char* name, char* fmt, ...)
536
+{
537
+    bool ret=false;
538
+    va_list va;
539
+
540
+    PYLOCK;
541
+
542
+    va_start(va, fmt);
543
+    PyObject* o = PyObject_VaCallMethod(py_dlg,name,fmt,va);
544
+    va_end(va);
545
+
546
+    if(!o) {
547
+
548
+	if(PyErr_ExceptionMatches(PyExc_AttributeError)){
549
+
550
+	    DBG("method %s is not implemented, trying default one\n",name);
551
+	    return true;
552
+	}
553
+
554
+	PyErr_Print();
555
+    }
556
+    else {
557
+        if(o && PyBool_Check(o) && (o == Py_True)) {
558
+
559
+	    ret = true;
560
+        }
561
+
562
+	Py_DECREF(o);
563
+    }
564
+    
565
+    return ret;
566
+}
567
+
568
+void IvrDialog::onSessionStart(const AmSipRequest& req)
569
+{
570
+    DBG("IvrDialog::onSessionStart\n");
571
+    setInOut(&playlist,&playlist);
572
+    AmB2BCallerSession::onSessionStart(req);
573
+}
574
+
575
+void IvrDialog::process(AmEvent* event) 
576
+{
577
+    DBG("IvrDialog::process\n");
578
+
579
+    AmAudioEvent* audio_event = dynamic_cast<AmAudioEvent*>(event);
580
+    if(audio_event && audio_event->event_id == AmAudioEvent::noAudio){
581
+
582
+	callPyEventHandler("onEmptyQueue", NULL);
583
+	event->processed = true;
584
+    }
585
+    
586
+    AmPluginEvent* plugin_event = dynamic_cast<AmPluginEvent*>(event);
587
+    if(plugin_event && plugin_event->name == "timer_timeout") {
588
+
589
+	callPyEventHandler("onTimer", "i", plugin_event->data.get(0).asInt());
590
+	event->processed = true;
591
+    }
592
+
593
+    if (!event->processed)
594
+      AmB2BCallerSession::process(event);
595
+
596
+    return;
597
+}
598
+
0 599
new file mode 100644
... ...
@@ -0,0 +1,128 @@
1
+/*
2
+ * $Id: Ivr.h,v 1.15.2.1 2005/09/02 13:47:46 rco Exp $
3
+ * Copyright (C) 2002-2003 Fhg Fokus
4
+ *
5
+ * This file is part of sems, a free SIP media server.
6
+ *
7
+ * This program is free software; you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation; either version 2 of the License, or
10
+ * (at your option) any later version
11
+ *
12
+ * This program is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
+ * GNU General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU General Public License
18
+ * along with this program; if not, write to the Free Software
19
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20
+ */
21
+
22
+#ifndef _IVR_H_
23
+#define _IVR_H_
24
+
25
+#define MOD_NAME "ivr"
26
+
27
+#include <Python.h>
28
+
29
+#include "AmB2BSession.h"
30
+#include "AmPlaylist.h"
31
+
32
+#ifdef IVR_WITH_TTS
33
+#include "flite.h"
34
+#endif
35
+
36
+#include <string>
37
+#include <map>
38
+using std::string;
39
+using std::map;
40
+
41
+class IvrDialog;
42
+
43
+struct IvrScriptDesc
44
+{
45
+    PyObject* mod;
46
+    PyObject* dlg_class;
47
+
48
+    IvrScriptDesc()
49
+	: mod(0), 
50
+	  dlg_class(0)
51
+    {}
52
+
53
+    IvrScriptDesc(const IvrScriptDesc& d)
54
+	: mod(d.mod), 
55
+	  dlg_class(d.dlg_class)
56
+    {}
57
+
58
+    IvrScriptDesc(PyObject* mod, 
59
+		  PyObject* dlg_class)
60
+	: mod(mod),
61
+	  dlg_class(dlg_class)
62
+    {}
63
+};
64
+
65
+
66
+class IvrFactory: public AmSessionFactory
67
+{
68
+    PyObject* ivr_module;
69
+    string script_path;
70
+    string default_script;
71
+
72
+    map<string,IvrScriptDesc> mod_reg;
73
+
74
+    AmDynInvokeFactory* user_timer_fact;
75
+
76
+    void init_python_interpreter();
77
+    void import_ivr_builtins();
78
+
79
+    void import_module(const char* modname);
80
+    void import_object(PyObject* m, 
81
+		       char* name, 
82
+		       PyTypeObject* type);
83
+
84
+    /** @return true if everything ok */
85
+    bool loadScript(const string& path);
86
+
87
+    void setScriptPath(const string& path);
88
+    bool checkCfg();
89
+
90
+    IvrDialog* newDlg(const string& name);
91
+    
92
+ public:
93
+    IvrFactory(const string& _app_name);
94
+
95
+    int onLoad();
96
+    AmSession* onInvite(const AmSipRequest& req);
97
+};
98
+
99
+
100
+class IvrDialog : public AmB2BCallerSession
101
+{
102
+    PyObject  *py_mod;
103
+    PyObject  *py_dlg;
104
+
105
+    bool callPyEventHandler(char* name, char* fmt, ...);
106
+    
107
+    void process(AmEvent* event);
108
+
109
+public:
110
+    AmDynInvoke* user_timer;
111
+    AmPlaylist playlist;
112
+
113
+    IvrDialog();
114
+    IvrDialog(AmDynInvoke* user_timer);
115
+    ~IvrDialog();
116
+
117
+    // must be called before everything else.
118
+    void setPyPtrs(PyObject *mod, PyObject *dlg);
119
+    
120
+    void onSessionStart(const AmSipRequest& req);
121
+/*     void onBye(const AmSipRequest& req); */
122
+/*     void onDtmf(int event, int duration_msec); */
123
+
124
+/*     void onOtherBye(const AmSipRequest& req); */
125
+/*     void onOtherReply(const AmSipReply& r); */
126
+};
127
+
128
+#endif
0 129
new file mode 100644
... ...
@@ -0,0 +1,321 @@
1
+#include "IvrAudio.h"
2
+#include "AmAudio.h"
3
+#include "AmSession.h"
4
+
5
+#include "log.h"
6
+
7
+#ifdef IVR_WITH_TTS
8
+
9
+#define TTS_CACHE_PATH "/tmp/"
10
+extern "C" cst_voice *register_cmu_us_kal();
11
+
12
+#endif //ivr_with_tts
13
+
14
+
15
+static PyObject* IvrAudioFile_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
16
+{
17
+    DBG("---------- IvrAudioFile_alloc -----------\n");
18
+    IvrAudioFile *self;
19
+
20
+    self = (IvrAudioFile *)type->tp_alloc(type, 0);
21
+	
22
+    if (self != NULL) {
23
+
24
+	self->af = new AmAudioFile();
25
+	if(!self->af){
26
+	    Py_DECREF(self);
27
+	    return NULL;
28
+	}
29
+
30
+#ifdef IVR_WITH_TTS
31
+	flite_init();
32
+	self->tts_voice = register_cmu_us_kal();
33
+	self->filename = new string();
34
+#endif
35
+
36
+    }
37
+
38
+    return (PyObject *)self;
39
+}
40
+
41
+static void IvrAudioFile_dealloc(IvrAudioFile* self)
42
+{
43
+    DBG("---------- IvrAudioFile_dealloc -----------\n");
44
+    delete self->af;
45
+    self->af = NULL;
46
+
47
+#ifdef IVR_WITH_TTS
48
+    if(self->del_file && !self->filename->empty())
49
+	unlink(self->filename->c_str());
50
+    delete self->filename;
51
+#endif
52
+
53
+    self->ob_type->tp_free((PyObject*)self);
54
+}
55
+
56
+static PyObject* IvrAudioFile_open(IvrAudioFile* self, PyObject* args)
57
+{
58
+    int                   ivr_open_mode;
59
+    char*                 filename;
60
+    bool                  is_tmp;
61
+    PyObject*             py_is_tmp = NULL;
62
+    AmAudioFile::OpenMode open_mode;
63
+
64
+    if(!PyArg_ParseTuple(args,"si|O",&filename,&ivr_open_mode,&py_is_tmp))
65
+	return NULL;
66
+
67
+    switch(ivr_open_mode){
68
+    case AUDIO_READ:
69
+	open_mode = AmAudioFile::Read;
70
+	break;
71
+    case AUDIO_WRITE:
72
+	open_mode = AmAudioFile::Write;
73
+	break;
74
+    default:
75
+	PyErr_SetString(PyExc_TypeError,"Unknown open mode");
76
+	return NULL;
77
+	break;
78
+    }
79
+
80
+    if((py_is_tmp == NULL) || (py_is_tmp == Py_False))
81
+	is_tmp = false;
82
+    else if(py_is_tmp == Py_True)
83
+	is_tmp = true;
84
+    else {
85
+	PyErr_SetString(PyExc_TypeError,"third parameter should be of type PyBool");
86
+	return NULL;
87
+    }
88
+
89
+    if(self->af->open(filename,open_mode,is_tmp)){
90
+	PyErr_SetString(PyExc_IOError,"Could not open file");
91
+	return NULL;
92
+    }
93
+
94
+    Py_INCREF(Py_None);
95
+    return Py_None;
96
+}
97
+
98
+static PyObject* IvrAudioFile_fpopen(IvrAudioFile* self, PyObject* args)
99
+{
100
+    int                   ivr_open_mode;
101
+    char*                 filename;
102
+    PyObject*             py_file = NULL;
103
+    AmAudioFile::OpenMode open_mode;
104
+
105
+    if(!PyArg_ParseTuple(args,"siO",&filename,&ivr_open_mode,&py_file))
106
+	return NULL;
107
+
108
+    switch(ivr_open_mode){
109
+    case AUDIO_READ:
110
+	open_mode = AmAudioFile::Read;
111
+	break;
112
+    case AUDIO_WRITE:
113
+	open_mode = AmAudioFile::Write;
114
+	break;
115
+    default:
116
+	PyErr_SetString(PyExc_TypeError,"Unknown open mode");
117
+	return NULL;
118
+	break;
119
+    }
120
+
121
+    FILE* fp = PyFile_AsFile(py_file);
122
+    if(!fp){
123
+	PyErr_SetString(PyExc_IOError,"Could not get FILE pointer");
124
+	return NULL;
125
+    }
126
+
127
+    if(self->af->fpopen(filename,open_mode,fp)){
128
+	PyErr_SetString(PyExc_IOError,"Could not open file");
129
+	return NULL;
130
+    }
131
+
132
+    Py_INCREF(Py_None);
133
+    return Py_None;
134
+}
135
+
136
+static PyObject* IvrAudioFile_rewind(IvrAudioFile* self, PyObject* args)
137
+{
138
+    self->af->rewind();
139
+    Py_INCREF(Py_None);
140
+    return Py_None;
141
+}
142
+
143
+#ifdef IVR_WITH_TTS
144
+static PyObject* IvrAudioFile_tts(PyObject* cls, PyObject* args)
145
+{
146
+    char* text;
147
+    if(!PyArg_ParseTuple(args,"s",&text))
148
+	return NULL;
149
+    
150
+    PyObject* constr_args = Py_BuildValue("(O)",Py_None);
151
+    PyObject* tts_file = PyObject_CallObject(cls,constr_args);
152
+    Py_DECREF(constr_args);
153
+
154
+    if(tts_file == NULL){
155
+	PyErr_Print();
156
+	PyErr_SetString(PyExc_RuntimeError,"could not create new IvrAudioFile object");
157
+	return NULL;
158
+    }
159
+
160
+    IvrAudioFile* self = (IvrAudioFile*)tts_file;
161
+
162
+    *self->filename = string(TTS_CACHE_PATH) + AmSession::getNewId() + string(".wav");
163
+    self->del_file = true;
164
+    flite_text_to_speech(text,self->tts_voice,self->filename->c_str());
165
+    
166
+    if(self->af->open(self->filename->c_str(),AmAudioFile::Read)){
167
+	Py_DECREF(tts_file);
168
+	PyErr_SetString(PyExc_IOError,"could not open TTS file");
169
+	return NULL;
170
+    }
171
+
172
+    return tts_file;
173
+}
174
+#endif
175
+    
176
+static PyObject* IvrAudioFile_close(IvrAudioFile* self, PyObject*)
177
+{
178
+    self->af->close();
179
+    Py_INCREF(Py_None);
180
+    return Py_None;
181
+}
182
+
183
+static PyObject* IvrAudioFile_getDataSize(IvrAudioFile* self, PyObject*)
184
+{
185
+    return PyInt_FromLong(self->af->getDataSize());
186
+}
187
+
188
+static PyObject* IvrAudioFile_setRecordTime(IvrAudioFile* self, PyObject* args)
189
+{
190
+    int rec_time;
191
+    if(!PyArg_ParseTuple(args,"i",&rec_time))
192
+	return NULL;
193
+
194
+    self->af->setRecordTime(rec_time);
195
+    
196
+    Py_INCREF(Py_None);
197
+    return Py_None;
198
+}
199
+
200
+static PyObject* IvrAudioFile_exportRaw(IvrAudioFile* self, PyObject*)
201
+{
202
+    if(self->af->getMode() == AmAudioFile::Write)
203
+	self->af->on_close();
204
+    
205
+    self->af->rewind();
206
+
207
+    return PyFile_FromFile(self->af->getfp(),"","rwb",NULL);
208
+}
209
+
210
+
211
+static PyMethodDef IvrAudioFile_methods[] = {
212
+    {"open", (PyCFunction)IvrAudioFile_open, METH_VARARGS,
213
+     "open the audio file"
214
+    },
215
+    {"fpopen", (PyCFunction)IvrAudioFile_fpopen, METH_VARARGS,
216
+     "open the audio file"
217
+    },
218
+    {"close", (PyCFunction)IvrAudioFile_close, METH_NOARGS,
219
+     "close the audio file"
220
+    },
221
+    {"rewind", (PyCFunction)IvrAudioFile_rewind, METH_NOARGS,
222
+     "rewind the audio file"
223
+    },
224
+    {"getDataSize", (PyCFunction)IvrAudioFile_getDataSize, METH_NOARGS,
225
+     "returns the recorded data size"
226
+    },
227
+    {"setRecordTime", (PyCFunction)IvrAudioFile_setRecordTime, METH_VARARGS,
228
+     "set the maximum record time in millisecond"
229
+    },
230
+    {"exportRaw", (PyCFunction)IvrAudioFile_exportRaw, METH_NOARGS,
231
+     "creates a new Python file with the actual file"
232
+     " and eventually flushes headers (audio->on_stop)"
233
+    },
234
+#ifdef IVR_WITH_TTS
235
+    {"tts", (PyCFunction)IvrAudioFile_tts, METH_CLASS | METH_VARARGS,
236
+     "text to speech"
237
+    },
238
+#endif
239
+    {NULL}  /* Sentinel */
240
+};
241
+
242
+
243
+static PyObject* IvrAudioFile_getloop(IvrAudioFile* self, void*)
244
+{
245
+    PyObject* loop = self->af->loop.get() ? Py_True : Py_False;
246
+    Py_INCREF(loop);
247
+    return loop;
248
+}
249
+
250
+static int IvrAudioFile_setloop(IvrAudioFile* self, PyObject* value, void*)
251
+{
252
+    if (value == NULL) {
253
+	PyErr_SetString(PyExc_TypeError, "Cannot delete the first attribute");
254
+	return -1;
255
+    }
256
+  
257
+    if(value == Py_True)
258
+	self->af->loop.set(true);
259
+
260
+    else if(value == Py_False)
261
+	self->af->loop.set(false);
262
+
263
+    else {
264
+	PyErr_SetString(PyExc_TypeError, 
265
+			"The first attribute value must be a boolean");
266
+	return -1;
267
+    }
268
+
269
+    return 0;
270
+}
271
+
272
+static PyGetSetDef IvrAudioFile_getseters[] = {
273
+    {"loop", 
274
+     (getter)IvrAudioFile_getloop, (setter)IvrAudioFile_setloop,
275
+     "repeat mode",
276
+     NULL},
277
+    {NULL}  /* Sentinel */
278
+};
279
+    
280
+PyTypeObject IvrAudioFileType = {
281
+	
282
+    PyObject_HEAD_INIT(NULL)
283
+    0,                         /*ob_size*/
284
+    "ivr.IvrAudioFile",        /*tp_name*/
285
+    sizeof(IvrAudioFile),      /*tp_basicsize*/
286
+    0,                         /*tp_itemsize*/
287
+    (destructor)IvrAudioFile_dealloc, /*tp_dealloc*/
288
+    0,                         /*tp_print*/
289
+    0,                         /*tp_getattr*/
290
+    0,                         /*tp_setattr*/
291
+    0,                         /*tp_compare*/
292
+    0,                         /*tp_repr*/
293
+    0,                         /*tp_as_number*/
294
+    0,                         /*tp_as_sequence*/
295
+    0,                         /*tp_as_mapping*/
296
+    0,                         /*tp_hash */
297
+    0,                         /*tp_call*/
298
+    0,                         /*tp_str*/
299
+    0,                         /*tp_getattro*/
300
+    0,                         /*tp_setattro*/
301
+    0,                         /*tp_as_buffer*/
302
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
303
+    "An audio file",           /*tp_doc*/
304
+    0,		               /* tp_traverse */
305
+    0,		               /* tp_clear */
306
+    0,		               /* tp_richcompare */
307
+    0,		               /* tp_weaklistoffset */
308
+    0,		               /* tp_iter */
309
+    0,		               /* tp_iternext */
310
+    IvrAudioFile_methods,      /* tp_methods */
311
+    0,                         /* tp_members */
312
+    IvrAudioFile_getseters,    /* tp_getset */
313
+    0,                         /* tp_base */
314
+    0,                         /* tp_dict */
315
+    0,                         /* tp_descr_get */
316
+    0,                         /* tp_descr_set */
317
+    0,                         /* tp_dictoffset */
318
+    0,                         /* tp_init */
319
+    0,                         /* tp_alloc */
320
+    IvrAudioFile_new,          /* tp_new */
321
+};
0 322
new file mode 100644
... ...
@@ -0,0 +1,33 @@
1
+#ifndef IvrAudio_h
2
+#define IvrAudio_h
3
+
4
+// Python stuff
5
+#include <Python.h>
6
+#include "structmember.h"
7
+
8
+#include "AmAudio.h"
9
+
10
+#define AUDIO_READ  1
11
+#define AUDIO_WRITE 2
12
+
13
+#ifdef IVR_WITH_TTS
14
+#include "flite.h"
15
+#endif
16
+
17
+// Data definition
18
+typedef struct {
19
+    
20
+    PyObject_HEAD
21
+    AmAudioFile* af;
22
+
23
+#ifdef IVR_WITH_TTS
24
+    cst_voice* tts_voice;
25
+    string*    filename;
26
+    bool       del_file;
27
+#endif
28
+    
29
+} IvrAudioFile;
30
+
31
+extern PyTypeObject IvrAudioFileType;
32
+
33
+#endif
0 34
new file mode 100644
... ...
@@ -0,0 +1,95 @@
1
+plug_in_name = py_sems
2
+
3
+COREPATH ?=../../core
4
+
5
+SCRIPT = Python
6
+TTS = y
7
+
8
+#
9
+# Python specific
10
+#  (no need to change this if you want to use perl)
11
+#
12
+# PYTHON_VERSION might also be 2.2 -- except for the use of GIL
13
+# do a ls /usr/include/python2.3/Python.h to see if it's there
14
+PY_VER = 2.3
15
+# adjust to point to python include path
16
+# can also be /usr/include/python$(PY_VER)
17
+# look for Python.h in the specified path
18
+# Python prefix is what you configured python with 
19
+# if you built from source (e.g. ./configure --with-prefix=/usr/local)
20
+# on debian it's often /usr, on SuSE and FreeBSD /usr/local
21
+PYTHON_PREFIX = /usr
22
+PYTHON_DIR = $(PYTHON_PREFIX)/include/python$(PY_VER)
23
+PYTHON_LIBDIR = $(PYTHON_PREFIX)/lib/python$(PY_VER)
24
+
25
+# put used Python modules from lib-dynload here, e.g. time, mysql, _cvs.so etc.
26
+PYTHON_DYNLOAD_MODULES = $(wildcard $(PYTHON_LIBDIR)/lib-dynload/*.so) \
27
+	$(wildcard $(PYTHON_LIBDIR)/site-packages/*.so)
28
+PYTHON_module_cflags = -I$(PYTHON_DIR)
29
+PYTHON_module_ldflags = -Xlinker --export-dynamic \
30
+			-L$(PYTHON_LIBDIR)/config \
31
+			-lpython$(PY_VER) $(wildcard sip/*.o)
32
+#\
33
+#$(PYTHON_DYNLOAD_MODULES)
34
+
35
+ifeq ($(TTS), y)
36
+#
37
+#   flite text to speech
38
+#
39
+# uncomment the next lines if you want to have flite text-to-speech (ivr.say("Hello there"); ) 
40
+FLITE_DIR = /usr/src/flite-1.2-release
41
+ALT_FLITE_DIR = /usr/include/flite
42
+IVR_TTS_module_ldflags =  -L$(FLITE_DIR)/lib -lm  -lflite_cmu_us_kal  -lflite_usenglish \
43
+	-lflite_cmulex -lflite
44
+IVR_TTS_module_cflags = -I$(FLITE_DIR)/include  -I$(ALT_FLITE_DIR) -DIVR_WITH_TTS
45
+endif
46
+
47
+LOCAL_INCLUDES = -I$(FLITE_DIR)/lang/usenglish
48
+
49
+# On FreeBSD, remove the following flags: -ldl -lpthread 
50
+module_ldflags = -ldl -lpthread -lutil -lm \
51
+	$(PYTHON_module_ldflags) \
52
+	$(IVR_TTS_module_ldflags)
53
+
54
+# for perl support:
55
+# -DIVR_PERL  `perl -MExtUtils::Embed -e ccopts `
56
+# for flite text-to-speech support -DIVR_WITH_TTS
57
+module_cflags  = \
58
+	$(PYTHON_module_cflags) \
59
+	$(IVR_TTS_module_cflags) \
60
+	$(PERL_module_cflags) \
61
+	$(module_additional_cflags)
62
+
63
+extra_target  = python_files
64
+extra_install = install_python_files
65
+
66
+py_src = $(notdir $(wildcard py/*.py))
67
+py_obj = $(py_src:.py=.pyc)
68
+
69
+
70
+ifeq (all,$(MAKECMDGOALS))
71
+.PHONY: python_files
72
+python_files: 
73
+	python$(PY_VER) py_comp -l -q py &&\
74
+	cp py/*.pyc $(COREPATH)/lib
75
+
76
+endif
77
+
78
+ifeq (module_package,$(MAKECMDGOALS))
79
+python_files:
80
+	python$(PY_VER) py_comp -l -q py
81
+
82
+endif
83
+
84
+include $(COREPATH)/plug-in/Makefile.app_module
85
+
86
+.PHONY: install_python_files
87
+install_python_files: $(modules-prefix)/$(modules-dir)
88
+	echo "Installing Python object files..."
89
+	for f in $(py_obj) ; do \
90
+		if [ -n "py/$$f" ]; then \
91
+			$(INSTALL-TOUCH) $(modules-prefix)/$(modules-dir)/$$f; \
92
+			$(INSTALL-MODULES) py/$$f $(modules-prefix)/$(modules-dir)/$$f; \
93
+		fi ; \
94
+	done
95
+
0 96
new file mode 100644
... ...
@@ -0,0 +1,595 @@
1
+/*
2
+ * $Id: PySems.cpp,v 1.26.2.1 2005/09/02 13:47:46 rco Exp $
3
+ * Copyright (C) 2002-2003 Fhg Fokus
4
+ *
5
+ * This file is part of sems, a free SIP media server.
6
+ *
7
+ * This program is free software; you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation; either version 2 of the License, or
10
+ * (at your option) any later version
11
+ *
12
+ * This program is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
+ * GNU General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU General Public License
18
+ * along with this program; if not, write to the Free Software
19
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20
+ */
21
+
22
+#include "PySemsAudio.h"
23
+#include "PySems.h"
24
+
25
+#include "AmConfigReader.h"
26
+#include "AmConfig.h"
27
+#include "log.h"
28
+#include "AmApi.h"
29
+#include "AmUtils.h"
30
+#include "AmSessionScheduler.h"
31
+#include "AmPlugIn.h"
32
+
33
+#include "sip/sipAPIpy_sems.h"
34
+#include "sip/sippy_semsPySemsDialog.h"
35
+
36
+#include <unistd.h>
37
+#include <pthread.h>
38
+#include <regex.h>
39
+#include <dirent.h>
40
+
41
+#include <set>
42
+using std::set;
43
+
44
+
45
+#define PYFILE_REGEX "(.+)\\.(py|pyc|pyo)$"
46
+
47
+
48
+EXPORT_SESSION_FACTORY(PySemsFactory,MOD_NAME);
49
+
50
+PyMODINIT_FUNC initpy_sems();
51
+
52
+struct PythonGIL
53
+{
54
+    PyGILState_STATE gst;
55
+
56
+    PythonGIL() { gst = PyGILState_Ensure(); }
57
+    ~PythonGIL(){ PyGILState_Release(gst);   }
58
+};
59
+
60
+
61
+// This must be the first declaration of every 
62
+// function using Python C-API.
63
+// But this is not necessary in function which
64
+// will get called from Python
65
+#define PYLOCK PythonGIL _py_gil
66
+
67
+extern "C" {
68
+
69
+    static PyObject* ivr_log(PyObject*, PyObject* args)
70
+    {
71
+	int level;
72
+	char *msg;
73
+
74
+	if(!PyArg_ParseTuple(args,"is",&level,&msg))
75
+	    return NULL;
76
+
77
+	if((level)<=log_level) {
78
+
79
+	    //if(level == L_ERR)
80
+	    //assert(0);
81
+
82
+	    if(log_stderr)
83
+		log_print( level, msg );
84
+	    else {
85
+		switch(level){
86
+		case L_ERR:
87
+		    syslog(LOG_ERR | L_FAC, "Error: %s", msg);
88
+		    break;
89
+		case L_WARN:
90
+		    syslog(LOG_WARNING | L_FAC, "Warning: %s", msg);
91
+		    break;
92
+		case L_INFO:
93
+		    syslog(LOG_INFO | L_FAC, "Info: %s", msg);
94
+		    break;
95
+		case L_DBG:
96
+		    syslog(LOG_DEBUG | L_FAC, "Debug: %s", msg);
97
+		    break;
98
+		}
99
+	    }
100
+	}
101
+	
102
+	Py_INCREF(Py_None);
103
+	return Py_None;
104
+    }
105
+
106
+    static PyObject* ivr_getHeader(PyObject*, PyObject* args)
107
+    {
108
+	char* headers;
109
+	char* header_name;
110
+	if(!PyArg_ParseTuple(args,"ss",&headers,&header_name))
111
+	    return NULL;
112
+
113
+	string res = getHeader(headers,header_name);
114
+	return PyString_FromString(res.c_str());
115
+    }
116
+
117
+
118
+    static PyMethodDef ivr_methods[] = {
119
+ 	{"log", (PyCFunction)ivr_log, METH_VARARGS,"Log a message using Sems' logging system"},
120
+	{"getHeader", (PyCFunction)ivr_getHeader, METH_VARARGS,"Python getHeader wrapper"},
121
+	{NULL}  /* Sentinel */
122
+    };
123
+}
124
+
125
+PySemsFactory::PySemsFactory(const string& _app_name)
126
+    : AmSessionFactory(_app_name),
127
+      user_timer_fact(NULL)
128
+{
129
+}
130
+
131
+void PySemsFactory::setScriptPath(const string& path)
132
+{
133
+    string python_path = script_path = path;
134
+
135
+    
136
+    if(python_path.length()){
137
+
138
+	python_path = AmConfig::PlugInPath + ":" + python_path;
139
+    }
140
+    else
141
+	python_path = AmConfig::PlugInPath;
142
+
143
+    char* old_path=0;
144
+    if((old_path = getenv("PYTHONPATH")) != 0)
145
+	if(strlen(old_path))
146
+	    python_path += ":" + string(old_path);
147
+
148
+    DBG("setting PYTHONPATH to: '%s'\n",python_path.c_str());
149
+    setenv("PYTHONPATH",python_path.c_str(),1);
150
+
151
+}
152
+
153
+void PySemsFactory::import_object(PyObject* m, char* name, PyTypeObject* type)
154
+{
155
+    if (PyType_Ready(type) < 0){
156
+	ERROR("PyType_Ready failed !\n");
157
+        return;
158
+    }
159
+    Py_INCREF(type);
160
+    PyModule_AddObject(m, name, (PyObject *)type);
161
+}
162
+
163
+void PySemsFactory::import_ivr_builtins()
164
+{
165
+    // ivr module - start
166
+    PyImport_AddModule("ivr");
167
+    ivr_module = Py_InitModule("ivr",ivr_methods);
168
+
169
+    // PySemsSipDialog (= AmSipDialog)
170
+    //import_object(ivr_module, "PySemsSipDialog", &PySemsSipDialogType);
171
+
172
+    // PySemsDialogBase
173
+    //import_object(ivr_module,"PySemsDialogBase",&PySemsDialogBaseType);
174
+
175
+
176
+    // PySemsAudioFile
177
+    import_object(ivr_module,"PySemsAudioFile",&PySemsAudioFileType);
178
+
179
+    PyModule_AddIntConstant(ivr_module, "AUDIO_READ",AUDIO_READ);
180
+    PyModule_AddIntConstant(ivr_module, "AUDIO_WRITE",AUDIO_WRITE);
181
+    // ivr module - end
182
+
183
+    // add log level for the log module
184
+    PyModule_AddIntConstant(ivr_module, "SEMS_LOG_LEVEL",log_level);
185
+
186
+    import_module("log");
187
+    initpy_sems();
188
+}
189
+
190
+void PySemsFactory::import_module(const char* modname)
191
+{
192
+    PyObject* py_mod_name = PyString_FromString(modname);
193
+    PyObject* py_mod = PyImport_Import(py_mod_name);
194
+    Py_DECREF(py_mod_name);
195
+    
196
+    if(!py_mod){
197
+	PyErr_Print();
198
+	ERROR("PySemsFactory: could not find python module '%s'.\n",modname);
199
+	ERROR("PySemsFactory: please check your installation.\n");
200
+	return;
201
+    }
202
+}
203
+
204
+void PySemsFactory::init_python_interpreter()
205
+{
206
+    Py_Initialize();
207
+    PyEval_InitThreads();
208
+    import_ivr_builtins();
209
+    PyEval_ReleaseLock();
210
+}
211
+
212
+PySemsDialog* PySemsFactory::newDlg(const string& name)
213
+{
214
+    PYLOCK;
215
+
216
+    map<string,PySemsScriptDesc>::iterator mod_it = mod_reg.find(name);
217
+    if(mod_it == mod_reg.end()){
218
+	ERROR("Unknown script name '%s'\n", name.c_str());
219
+	throw AmSession::Exception(500,"Unknown Application");
220
+    }
221
+
222
+    PySemsScriptDesc& mod_desc = mod_it->second;
223
+
224
+    AmDynInvoke* user_timer = user_timer_fact->getInstance();
225
+    if(!user_timer){
226
+	ERROR("could not get a user timer reference\n");
227
+	throw AmSession::Exception(500,"could not get a user timer reference");
228
+    }