diff --git a/mail.cfg b/mail.cfg
new file mode 100644
index 0000000..5417cf5
--- /dev/null
+++ b/mail.cfg
@@ -0,0 +1,16 @@
+[mail]
+server = send.example.com
+port = 587
+send_from = raspi@example.de
+password = verynicepassword
+send_to = some@email.example
+subject = Message from {caller}
+title = Neue Sprachnachricht
+title_html = Anrufbeantworter
+epilog_html = Diese E-Mail wurde automatisch verfasst.
+content = Der Anrufer: {name} ({caller}) hat für Sie auf dem Anrufbeantworter eine Nachricht hinterlassen. Sie finden die Sprachnachricht im Anhang dieser E-Mail.
+label_from = Anruf von
+label_for = für die Rufnummer
+label_date = Datum
+label_time = Uhrzeit
+label_length = Aufnahmelänge
diff --git a/mail.html b/mail.html
new file mode 100644
index 0000000..e0fdd63
--- /dev/null
+++ b/mail.html
@@ -0,0 +1,96 @@
+
+
+
+ {title}
+
+
+
+
+
+
+
+
+
+
+ |
+
+
+
+
+ |
+
+
+
+
+
+
+ {label_from}:
+ |
+
+ {name} ({caller})
+ |
+
+
+
+ {label_for}:
+ |
+
+ {number}
+ |
+
+
+
+ {label_date}:
+ |
+
+ {date}
+ |
+
+
+
+ {label_time}:
+ |
+
+ {time}
+ |
+
+
+
+ {label_length}:
+ |
+
+ {length}
+ |
+
+
+ |
+
+
+
+
+
+
+ {epilog_html}
+ |
+
+
+ |
+
+
+ |
+
+
+
+
diff --git a/mail.py b/mail.py
index d5b2bbf..7379ac2 100755
--- a/mail.py
+++ b/mail.py
@@ -1,59 +1,122 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
-import sys
+import re
+import argparse
+import configparser
+import datetime
+import html
+import math
import smtplib
from os.path import basename
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
-from email.utils import COMMASPACE, formatdate
+from email.utils import formatdate
+from email import charset
+from mutagen.mp3 import MP3
-# config
-server = "send.example.com"
-port = 587
-send_from = "raspi@example.de"
-password = "verynicepassword"
-send_to = "some@email.example"
-subject = "Message from your answering machine"
+def send_mail(args):
+ config = configparser.ConfigParser()
+ config.read(args.config)
+ config = config['mail']
-def send_mail(text, f):
+ subject = config['subject']
+ send_from = config['send_from']
+ send_to = config['send_to']
- msg = MIMEMultipart()
+ dt = datetime.datetime.now()
+ try:
+ audio = MP3(args.filename)
+ delta = datetime.timedelta(math.ceil(audio.info.length))
+ length = str(delta)
+ dt -= delta
+ except Exception as exc:
+ length = str(exc)
+
+ contents = {
+ 'caller': args.caller,
+ 'name': args.name,
+ 'number': args.number,
+ 'date': str(dt.date()),
+ 'time': dt.time().strftime('%H:%S'),
+ 'length': length,
+ 'subject': subject,
+ 'title': config['title'],
+ 'title_html': config['title_html'],
+ 'epilog_html': config['epilog_html'],
+ 'label_from': config['label_from'],
+ 'label_for': config['label_for'],
+ 'label_date': config['label_date'],
+ 'label_time': config['label_time'],
+ 'label_length': config['label_length'],
+ }
+ contents['content'] = config['content'].format(**contents)
+
+ msg = MIMEMultipart(boundary="==Voice_Box==multipart/mixed==0==")
msg['From'] = send_from
msg['To'] = send_to
msg['Date'] = formatdate(localtime=True)
- msg['Subject'] = subject
+ msg['Subject'] = subject.format(**contents)
+
+ cs = charset.Charset('utf-8')
+ cs.body_encoding = charset.QP
+
+ body = config.get('body', '''{title}:
- msg.attach(MIMEText(text))
+{content}
+{label_from}: {name} ({caller})
+{label_for}: {number}
+{label_date}: {date}
+{label_time}: {time}
+{label_length}: {length}
+''')
+ text = MIMEMultipart('alternative', boundary="==Voice_Box==multipart/alternative==1==")
+ text.attach(MIMEText(body.format(**contents), 'plain', cs))
try:
- with open(f, "rb") as fil:
- part = MIMEApplication(
- fil.read(),
- Name=basename(f)
- )
- part['Content-Disposition'] = 'attachment; filename="%s"' % basename(f)
- msg.attach(part)
- except IOError as e:
- print "Can not read file \""+f+"\": I/O error({0}): {1}".format(e.errno, e.strerror)
- except:
- print "Can not read file", sys.exc_info()[0]
- raise
-
- s = smtplib.SMTP(server, port)
- # s.debuglevel = 1
- s.ehlo()
- s.starttls()
- # s.ehlo
- s.login(send_from, password)
- s.sendmail(send_from, send_to, msg.as_string())
- s.quit()
-
- # smtp.close()
-
-if len(sys.argv) == 3:
- send_mail(sys.argv[1],sys.argv[2])
-else:
- print"provide two arguments: \"text\" \"file\""
+ with open('mail.html') as fd:
+ body_html = re.sub(r'^\s*', '', fd.read())
+ text.attach(MIMEText(body_html.format(**{key: html.escape(value) for key, value in contents.items()}), 'html', cs))
+ except IOError:
+ pass
+ msg.attach(text)
+
+ with open(args.filename, "rb") as fd:
+ part = MIMEApplication(
+ fd.read(),
+ Name=basename(args.filename)
+ )
+ filename = basename(args.filename).replace('"', '').replace('\\', '')
+ part['Content-Disposition'] = 'attachment; filename="%s"' % (filename,)
+ msg.attach(part)
+
+ with smtplib.SMTP(config['server'], int(config['port'])) as s:
+ s.ehlo()
+ s.starttls()
+ s.login(send_from, config['password'])
+ s.sendmail(send_from, send_to, msg.as_string())
+ print('OK: email sent')
+
+# FIXME: handle such errors. What to do then?
+# Traceback (most recent call last):
+# File "./mail.py", line 102, in
+# send_mail(args)
+# File "./mail.py", line 91, in send_mail
+# s.sendmail(send_from, send_to, msg.as_string())
+# File "/usr/lib/python3.7/smtplib.py", line 888, in sendmail
+# raise SMTPDataError(code, resp)
+# smtplib.SMTPDataError: (554, b'5.7.0 Your message could not be sent. The limit on the number of allowed outgoing messages was exceeded. Try again later.')
+
+
+if __name__ == '__main__':
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--config', default='mail.cfg')
+ parser.add_argument('--name', default='Name unknown')
+ parser.add_argument('number')
+ parser.add_argument('caller')
+ parser.add_argument('filename')
+ args = parser.parse_args()
+ send_mail(args)
diff --git a/mail.sh b/mail.sh
index e4f44a6..23b823e 100755
--- a/mail.sh
+++ b/mail.sh
@@ -1,10 +1,10 @@
-#!/bin/bash
+#!/bin/sh
echo "compress-then-send script"
-text=$1
-filename=$2
+number="$1"
+callerid="$2"
+filename="$3"
lame "$filename"
filename="${filename%.*}"
-./mail.py "Call by $text recorded. Here is the file" "$filename.mp3"
-
+./mail.py "$number" "$callerid" "$filename.mp3"
diff --git a/sipserv.c b/sipserv.c
index 8d62285..31c09cd 100644
--- a/sipserv.c
+++ b/sipserv.c
@@ -12,14 +12,14 @@
Dependencies:
- PJSUA API (PJSIP)
- eSpeak
-
+
References :
http://www.pjsip.org/
http://www.pjsip.org/docs/latest/pjsip/docs/html/group__PJSUA__LIB.htm
http://espeak.sourceforge.net/
http://binerry.de/post/29180946733/raspberry-pi-caller-and-answering-machine
https://github.com/fabianhu/Sip-Pi
-
+
================================================================================
This tool is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -60,7 +60,7 @@ Lesser General Public License for more details.
#define MAX_DTMF_SETTINGS 9
// struct for app dtmf settings
-struct dtmf_config {
+struct dtmf_config {
int id;
int active;
int processing_active;
@@ -71,7 +71,7 @@ struct dtmf_config {
};
// struct for app configuration settings
-struct app_config {
+struct app_config {
char *sip_domain;
char *sip_user;
char *sip_password;
@@ -84,7 +84,7 @@ struct app_config {
char *AfterMath;
char *log_file;
struct dtmf_config dtmf_cfg[MAX_DTMF_SETTINGS];
-} app_cfg;
+} app_cfg;
// global holder vars for further app arguments
char *tts_file = "play.wav";
@@ -132,12 +132,12 @@ int main(int argc, char *argv[])
{
// first set some default values
app_cfg.record_calls = 0;
- app_cfg.silent_mode = 0;
+ app_cfg.silent_mode = 0;
// print infos
log_message("SIP Call - Simple TTS/DTMF-based answering machine\n");
log_message("==================================================\n");
-
+
// register signal handler for break-in-keys (e.g. ctrl+c)
signal(SIGINT, signal_handler);
signal(SIGKILL, signal_handler);
@@ -163,19 +163,19 @@ int main(int argc, char *argv[])
{
// display usage info and exit app
usage(0);
- exit(0);
+ exit(0);
}
-
+
// check for config file location
if (!strcasecmp(argv[arg], "--config-file"))
{
if (argc >= (arg+1))
{
- app_cfg.log_file = argv[arg+1];
+ app_cfg.log_file = argv[arg+1];
}
continue;
}
-
+
// check for silent mode option
char *s;
try_get_argument(arg, "-s", &s, argc, argv);
@@ -185,15 +185,15 @@ int main(int argc, char *argv[])
continue;
}
}
- }
-
+ }
+
if (!app_cfg.log_file)
{
// too few arguments specified - display usage info and exit app
usage(1);
exit(1);
}
-
+
// read app configuration from config file
parse_config_file(app_cfg.log_file);
@@ -204,7 +204,7 @@ int main(int argc, char *argv[])
usage(2); // fixme does not show after file has been opened.
exit(1);
}
-
+
if (app_cfg.announcement_file)
{
log_message("Announcement mode\n");
@@ -228,49 +228,49 @@ int main(int argc, char *argv[])
fclose(file);
}
}
-
+
// generate texts
log_message("Generating texts ... ");
-
- char tts_buffer[1024];
+
+ char tts_buffer[1024];
strcpy(tts_buffer, app_cfg.tts);
strcat(tts_buffer, " ");
-
+
for (i = 0; i < MAX_DTMF_SETTINGS; i++)
{
struct dtmf_config *d_cfg = &app_cfg.dtmf_cfg[i];
-
+
if (d_cfg->active == 1)
{
strcat(tts_buffer, d_cfg->tts_intro);
strcat(tts_buffer, " ");
}
}
-
+
log_message("Done.\n");
-
+
// synthesizing speech
log_message("Synthesizing speech ... ");
-
+
int synth_status = -1;
synth_status = synthesize_speech(tts_buffer, tts_file, app_cfg.language);
- if (synth_status != 0) error_exit("Error while creating phone text", synth_status);
+ if (synth_status != 0) error_exit("Error while creating phone text", synth_status);
log_message("Done.\n");
-
+
// setup up sip library pjsua
setup_sip();
-
+
// create account and register to sip server
register_sip();
-
+
// app loop
for (;;) {
sleep(10); // avoid locking up the system
}
-
+
// exit app
app_exit();
-
+
return 0;
}
@@ -321,7 +321,7 @@ static void usage(int error)
puts (" should return a \"1\" as first char, if yes.");
puts (" the wildcard # will be replaced with the calling phone number in the command");
puts (" am=string aftermath: command to be executed after call ends. Will be called with two parameters: $1 = Phone number $2 = recorded file name");
-
+
fflush(stdout);
}
@@ -329,18 +329,18 @@ static void usage(int error)
static int try_get_argument(int arg, char *arg_id, char **arg_val, int argc, char *argv[])
{
int found = 0;
-
+
// check if actual argument is searched argument
- if (!strcasecmp(argv[arg], arg_id))
+ if (!strcasecmp(argv[arg], arg_id))
{
// check if actual argument has a value
if (argc >= (arg+1))
{
// set value
- *arg_val = argv[arg+1];
+ *arg_val = argv[arg+1];
found = 1;
}
- }
+ }
return found;
}
@@ -350,55 +350,55 @@ static void parse_config_file(char *cfg_file)
// open config file
char line[200];
FILE *file = fopen(cfg_file, "r");
-
+
if (file!=NULL)
{
// start parsing file
while(fgets(line, 200, file) != NULL)
{
char *arg, *val;
-
+
// ignore comments and just new lines
if(line[0] == '#') continue;
if(line[0] == '\n') continue;
-
+
// split string at '='-char
arg = strtok(line, "=");
- if (arg == NULL) continue;
+ if (arg == NULL) continue;
val = strtok(NULL, "=");
-
+
// check for new line char and remove it
char *nl_check;
nl_check = strstr (val, "\n");
if (nl_check != NULL) strncpy(nl_check, " ", 1);
-
+
// remove trailing spaces
-
-
+
+
// duplicate string for having own instance of it
- char *arg_val = strdup(val);
-
+ char *arg_val = strdup(val);
+
// check for sip domain argument
- if (!strcasecmp(arg, "sd"))
+ if (!strcasecmp(arg, "sd"))
{
app_cfg.sip_domain = trim_string(arg_val);
continue;
}
-
+
// check for sip user argument
- if (!strcasecmp(arg, "su"))
+ if (!strcasecmp(arg, "su"))
{
app_cfg.sip_user = trim_string(arg_val);
continue;
}
-
+
// check for sip domain argument
- if (!strcasecmp(arg, "sp"))
+ if (!strcasecmp(arg, "sp"))
{
app_cfg.sip_password = trim_string(arg_val);
continue;
}
-
+
// check for language argument
if (!strcasecmp(arg, "ln"))
{
@@ -407,12 +407,12 @@ static void parse_config_file(char *cfg_file)
}
// check for record calls argument
- if (!strcasecmp(arg, "rc"))
+ if (!strcasecmp(arg, "rc"))
{
app_cfg.record_calls = atoi(val);
continue;
}
-
+
// check for announcement file argument
if (!strcasecmp(arg, "af"))
{
@@ -435,19 +435,19 @@ static void parse_config_file(char *cfg_file)
}
// check for silent mode argument
- if (!strcasecmp(arg, "s"))
+ if (!strcasecmp(arg, "s"))
{
app_cfg.silent_mode = atoi(val);
continue;
}
-
+
// check for tts intro
- if (!strcasecmp(arg, "tts"))
+ if (!strcasecmp(arg, "tts"))
{
app_cfg.tts = arg_val;
continue;
}
-
+
// check for a dtmf argument
char dtmf_id[1];
char dtmf_setting[25];
@@ -455,42 +455,42 @@ static void parse_config_file(char *cfg_file)
{
// parse dtmf id (key)
int d_id;
- d_id = atoi(dtmf_id);
+ d_id = atoi(dtmf_id);
- // check if actual dtmf id blasts maxium settings
+ // check if actual dtmf id blasts maxium settings
if (d_id >= MAX_DTMF_SETTINGS) continue;
-
+
// get pointer to actual dtmf_cfg entry
struct dtmf_config *d_cfg = &app_cfg.dtmf_cfg[d_id-1];
-
+
// check for dtmf active setting
if (!strcasecmp(dtmf_setting, "active"))
{
d_cfg->active = atoi(val);
continue;
}
-
+
// check for dtmf description setting
if (!strcasecmp(dtmf_setting, "description"))
{
d_cfg->description = arg_val;
continue;
}
-
+
// check for dtmf tts intro setting
if (!strcasecmp(dtmf_setting, "tts-intro"))
{
d_cfg->tts_intro = arg_val;
continue;
}
-
+
// check for dtmf tts answer setting
if (!strcasecmp(dtmf_setting, "tts-answer"))
{
d_cfg->tts_answer = arg_val;
continue;
}
-
+
// check for dtmf cmd setting
if (!strcasecmp(dtmf_setting, "cmd"))
{
@@ -498,7 +498,7 @@ static void parse_config_file(char *cfg_file)
continue;
}
}
-
+
// write warning if unknown configuration setting is found
char warning[200];
sprintf(warning, "Warning: Unknown configuration with arg '%s' and val '%s'\n", arg, val);
@@ -520,9 +520,9 @@ static void parse_config_file(char *cfg_file)
static char *trim_string(char *str)
{
while (isspace(*str)) ++str;
-
+
char *s = (char *)str;
-
+
size_t size;
char *end;
@@ -550,31 +550,31 @@ static void log_message(char *message)
static void setup_sip(void)
{
pj_status_t status;
-
+
log_message("Setting up pjsua ... ");
-
- // create pjsua
+
+ // create pjsua
status = pjsua_create();
if (status != PJ_SUCCESS) error_exit("Error in pjsua_create()", status);
-
- // configure pjsua
+
+ // configure pjsua
pjsua_config cfg;
pjsua_config_default(&cfg);
-
- // enable just 1 simultaneous call
+
+ // enable just 1 simultaneous call
cfg.max_calls = 1;
-
- // callback configuration
+
+ // callback configuration
cfg.cb.on_incoming_call = &on_incoming_call;
cfg.cb.on_call_media_state = &on_call_media_state;
cfg.cb.on_call_state = &on_call_state;
cfg.cb.on_dtmf_digit = &on_dtmf_digit;
-
+
// logging configuration
- pjsua_logging_config log_cfg;
+ pjsua_logging_config log_cfg;
pjsua_logging_config_default(&log_cfg);
log_cfg.console_level = PJSUA_LOG_LEVEL;
-
+
// media configuration
pjsua_media_config media_cfg;
pjsua_media_config_default(&media_cfg);
@@ -582,27 +582,27 @@ static void setup_sip(void)
media_cfg.clock_rate = 8000;
media_cfg.snd_clock_rate = 8000;
media_cfg.quality = 10;
-
- // initialize pjsua
+
+ // initialize pjsua
status = pjsua_init(&cfg, &log_cfg, &media_cfg);
if (status != PJ_SUCCESS) error_exit("Error in pjsua_init()", status);
-
+
// add udp transport
pjsua_transport_config udpcfg;
pjsua_transport_config_default(&udpcfg);
-
+
udpcfg.port = 5060;
status = pjsua_transport_create(PJSIP_TRANSPORT_UDP, &udpcfg, NULL);
if (status != PJ_SUCCESS) error_exit("Error creating transport", status);
-
+
// initialization is done, start pjsua
status = pjsua_start();
if (status != PJ_SUCCESS) error_exit("Error starting pjsua", status);
-
+
// disable sound - use null sound device
status = pjsua_set_null_snd_dev();
if (status != PJ_SUCCESS) error_exit("Error disabling audio", status);
-
+
log_message("Done.\n");
}
@@ -610,21 +610,21 @@ static void setup_sip(void)
static void register_sip(void)
{
pj_status_t status;
-
+
log_message("Registering account ... ");
-
+
// prepare account configuration
pjsua_acc_config cfg;
pjsua_acc_config_default(&cfg);
-
+
// build sip-user-url
char sip_user_url[40];
sprintf(sip_user_url, "sip:%s@%s", app_cfg.sip_user, app_cfg.sip_domain);
-
+
// build sip-provder-url
char sip_provider_url[40];
sprintf(sip_provider_url, "sip:%s", app_cfg.sip_domain);
-
+
// create and define account
cfg.id = pj_str(sip_user_url);
cfg.reg_uri = pj_str(sip_provider_url);
@@ -634,11 +634,11 @@ static void register_sip(void)
cfg.cred_info[0].username = pj_str(app_cfg.sip_user);
cfg.cred_info[0].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
cfg.cred_info[0].data = pj_str(app_cfg.sip_password);
-
+
// add account
status = pjsua_acc_add(&cfg, PJ_TRUE, &acc_id);
if (status != PJ_SUCCESS) error_exit("Error adding account", status);
-
+
log_message("Done.\n");
}
@@ -646,25 +646,25 @@ static void register_sip(void)
static void create_player(pjsua_call_id call_id, char *file)
{
// get call infos
- pjsua_call_info ci;
+ pjsua_call_info ci;
pjsua_call_get_info(call_id, &ci);
-
+
pj_str_t name;
pj_status_t status = PJ_ENOTFOUND;
-
+
log_message("Creating player ... ");
-
- // create player for playback media
+
+ // create player for playback media
status = pjsua_player_create(pj_cstr(&name, file), PJMEDIA_FILE_NO_LOOP, &play_id);
if (status != PJ_SUCCESS) error_exit("Error playing sound-playback", status);
-
+
// connect active call to media player
pjsua_conf_connect(pjsua_player_get_conf_port(play_id), ci.conf_slot);
-
+
// get media port (play_port) from play_id
status = pjsua_player_get_port(play_id, &play_port);
- if (status != PJ_SUCCESS) error_exit("Error getting sound player port", status);
-
+ if (status != PJ_SUCCESS) error_exit("Error getting sound player port", status);
+
log_message("Done.\n");
}
@@ -674,17 +674,17 @@ static void create_recorder(pjsua_call_info ci)
// specify target file
pj_str_t rec_file = pj_str(rec_ans_file);
pj_status_t status = PJ_ENOTFOUND;
-
+
log_message("Creating recorder ... ");
-
+
// Create recorder for call
status = pjsua_recorder_create(&rec_file, 0, NULL, 0, 0, &rec_id); // don't forget to destroy recorder, to have the file written.
if (status != PJ_SUCCESS) error_exit("Error recording answer", status);
-
+
// connect active call to call recorder
- pjsua_conf_port_id rec_port = pjsua_recorder_get_conf_port(rec_id);
+ pjsua_conf_port_id rec_port = pjsua_recorder_get_conf_port(rec_id);
pjsua_conf_connect(ci.conf_slot, rec_port);
-
+
log_message("Done.\n");
}
@@ -710,11 +710,11 @@ int recorder_destroy(pjsua_player_id id) {
static int synthesize_speech(char *speech, char *file, char* language)
{
int speech_status = -1;
-
+
char speech_command[1024];
sprintf(speech_command, "espeak -v%s -a%i -k%i -s%i -p%i -w %s '%s'", language, ESPEAK_AMPLITUDE, ESPEAK_CAPITALS_PITCH, ESPEAK_SPEED, ESPEAK_PITCH, file, speech);
speech_status = system(speech_command);
-
+
return speech_status;
}
@@ -838,7 +838,7 @@ static void on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id, pjsip_r
PJ_UNUSED_ARG(acc_id);
PJ_UNUSED_ARG(rdata);
-
+
current_call = call_id;
FileNameFromCallInfo(filename,sipNr,ci);
@@ -904,16 +904,16 @@ static void on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id, pjsip_r
static void on_call_media_state(pjsua_call_id call_id)
{
// get call infos
- pjsua_call_info ci;
+ pjsua_call_info ci;
pjsua_call_get_info(call_id, &ci);
-
+
pj_status_t status = PJ_ENOTFOUND;
// check state if call is established/active
if (ci.media_status == PJSUA_CALL_MEDIA_ACTIVE) {
-
- log_message("Call media activated.\n");
-
+
+ log_message("Call media activated.\n");
+
// create and start media player
if(app_cfg.announcement_file)
{
@@ -929,7 +929,7 @@ static void on_call_media_state(pjsua_call_id call_id)
{
create_recorder(ci);
}
- }
+ }
}
// handler for call-state-change-events
@@ -938,25 +938,25 @@ static void on_call_state(pjsua_call_id call_id, pjsip_event *e)
// get call infos
pjsua_call_info ci;
pjsua_call_get_info(call_id, &ci);
-
+
// prevent warning about unused argument e
PJ_UNUSED_ARG(e);
-
+
// check call state
- if (ci.state == PJSIP_INV_STATE_CONFIRMED)
+ if (ci.state == PJSIP_INV_STATE_CONFIRMED)
{
log_message("Call confirmed.\n");
-
+
// ensure that message is played from start
if (play_id != PJSUA_INVALID_ID)
{
pjmedia_wav_player_port_set_pos(play_port, 0);
}
}
- if (ci.state == PJSIP_INV_STATE_DISCONNECTED)
+ if (ci.state == PJSIP_INV_STATE_DISCONNECTED)
{
log_message("Call disconnected.\n");
-
+
// disable player
player_destroy(play_id);
// dont't forget the recorder!
@@ -964,13 +964,13 @@ static void on_call_state(pjsua_call_id call_id, pjsip_event *e)
{
// ok, recorder has been destroyed successfully, there should be a file too.
log_message("a file has been recorded.\n");
-
+
// process the Aftermath, if we have any.
if(app_cfg.AfterMath)
{
char result[RESULTSIZE];
char command[300];
- sprintf(command,"%s \"%s\" \"%s\"", app_cfg.AfterMath, lastNumber ,rec_ans_file);
+ sprintf(command,"%s \"%s\" \"%s\" \"%s\"", app_cfg.AfterMath, ci.local_info.ptr, lastNumber, rec_ans_file);
log_message(command);
log_message("\n");
@@ -986,58 +986,58 @@ static void on_call_state(pjsua_call_id call_id, pjsip_event *e)
// handler for dtmf-events
-static void on_dtmf_digit(pjsua_call_id call_id, int digit)
+static void on_dtmf_digit(pjsua_call_id call_id, int digit)
{
// get call infos
- pjsua_call_info ci;
+ pjsua_call_info ci;
pjsua_call_get_info(call_id, &ci);
-
+
// work on detected dtmf digit
int dtmf_key = digit - 48;
-
+
char info[100];
sprintf(info, "DTMF command detected: %i\n", dtmf_key);
log_message(info);
-
+
struct dtmf_config *d_cfg = &app_cfg.dtmf_cfg[dtmf_key-1];
if (d_cfg->processing_active == 0)
{
d_cfg->processing_active = 1;
-
+
if (d_cfg->active == 1)
{
log_message("Active DTMF command found for received digit.\n");
log_message("Creating answer ... ");
-
+
int error = 0;
char command[100];
char result[RESULTSIZE];
-
+
strcpy(command, d_cfg->cmd);
-
+
error = callBash(command, result);
if (!error)
- {
+ {
player_destroy(play_id);
recorder_destroy(rec_id);
-
+
char tts_buffer[200];
sprintf(tts_buffer, d_cfg->tts_answer, result);
-
+
int synth_status = -1;
synth_status = synthesize_speech(tts_buffer, tts_answer_file, app_cfg.language);
- if (synth_status != 0) log_message(" (Failed to synthesize speech) ");
-
+ if (synth_status != 0) log_message(" (Failed to synthesize speech) ");
+
create_player(call_id, tts_answer_file);
}
-
+
log_message("Done.\n");
}
else
{
log_message("No active DTMF command found for received digit.\n");
}
-
+
d_cfg->processing_active = 0;
}
else
@@ -1047,7 +1047,7 @@ static void on_dtmf_digit(pjsua_call_id call_id, int digit)
}
// handler for "break-in-key"-events (e.g. ctrl+c)
-static void signal_handler(int signal)
+static void signal_handler(int signal)
{
// exit app
app_exit();
@@ -1060,17 +1060,17 @@ static void app_exit()
{
app_exiting = 1;
log_message("Stopping application ... \n");
-
+
// check if player/recorder is active and stop them
player_destroy(play_id);
recorder_destroy(rec_id);
-
+
// hangup open calls and stop pjsua
pjsua_call_hangup_all();
pjsua_destroy();
-
+
log_message("Done.\n");
-
+
exit(0);
}
}
@@ -1084,15 +1084,15 @@ static void error_exit(const char *title, pj_status_t status)
log_message("App Error Exit\n");
pjsua_perror("SIP Call", title, status);
-
+
// check if player/recorder is active and stop them
player_destroy(play_id);
recorder_destroy(rec_id);
-
+
// hangup open calls and stop pjsua
pjsua_call_hangup_all();
pjsua_destroy();
-
+
exit(1);
}
}