From 3123aba1bf6a4a357a524d9b885cd8f4c1d9dd08 Mon Sep 17 00:00:00 2001 From: Juha Heinanen Date: Fri, 1 Jun 2007 17:36:38 +0000 Subject: [PATCH] * Added MySQL audio and template storage option for voicemail application. * Simplified conference application by removing caching of audio from MySQL to file system. git-svn-id: http://svn.berlios.de/svnroot/repos/sems/trunk@343 8eb893ce-cfd4-0310-b710-fb5ebe64c474 --- apps/conference/Conference.cpp | 95 +++++----- apps/conference/Makefile | 2 +- apps/voicemail/AnswerMachine.cpp | 302 +++++++++++++++++++++++++++++- apps/voicemail/AnswerMachine.h | 12 ++ apps/voicemail/Makefile | 20 ++ apps/voicemail/etc/voicemail.conf | 19 +- doc/Readme.conference | 6 +- doc/Readme.voicemail | 87 +++++++-- 8 files changed, 460 insertions(+), 83 deletions(-) diff --git a/apps/conference/Conference.cpp b/apps/conference/Conference.cpp index 39759dc9..32b7b4d7 100644 --- a/apps/conference/Conference.cpp +++ b/apps/conference/Conference.cpp @@ -43,8 +43,8 @@ #define DEFAULT_AUDIO_TABLE "default_audio" #define DOMAIN_AUDIO_TABLE "domain_audio" #define LONELY_USER_MSG "first_participant_msg" -#define JOIN_SOUND "join_sound" -#define DROP_SOUND "drop_sound" +#define JOIN_SOUND "join_snd" +#define DROP_SOUND "drop_snd" #endif #define APP_NAME "conference" @@ -67,79 +67,68 @@ PlayoutType ConferenceFactory::m_PlayoutType = ADAPTIVE_PLAYOUT; mysqlpp::Connection ConferenceFactory::Connection(mysqlpp::use_exceptions); #endif -int cache_audio_file(string message, string domain, string language, +int get_audio_file(string message, string domain, string language, string *audio_file) { + string query_string; + if (language.empty()) { if (domain.empty()) { *audio_file = string("/tmp/") + APP_NAME + "_" + message + ".wav"; + query_string = "select audio from " + string(DEFAULT_AUDIO_TABLE) + " where application='" + APP_NAME + "' and message='" + message + "' and language is null"; } else { *audio_file = "/tmp/" + domain + "_" + APP_NAME + "_" + message + ".wav"; + query_string = "select audio from " + string(DOMAIN_AUDIO_TABLE) + " where application='" + APP_NAME + "' and message='" + message + "' and domain='" + domain + "' and language is null"; } } else { if (domain.empty()) { *audio_file = string("/tmp/") + APP_NAME + "_" + message + "_" + language + ".wav"; + query_string = "select audio from " + string(DEFAULT_AUDIO_TABLE) + " where application='" + APP_NAME + "' and message='" + message + "' and language='" + language + "'"; } else { *audio_file = "/tmp/" + domain + "_" + APP_NAME + "_" + message + "_" + language + ".wav"; + query_string = "select audio from " + string(DOMAIN_AUDIO_TABLE) + " where application='" + APP_NAME + "' and message='" + message + "' and domain='" + domain + "' and language='" + language + "'"; } } - - if (file_exists(*audio_file)) { - - return 1; - } else { - - try { + try { - mysqlpp::Query query = ConferenceFactory::Connection.query(); + mysqlpp::Query query = ConferenceFactory::Connection.query(); - string query_string, table; - if (domain.empty()) { - table = DEFAULT_AUDIO_TABLE; - } else { - table = DOMAIN_AUDIO_TABLE; - } - if (language.empty()) { - query_string = "select audio from " + table + " where application='conference' and message='" + message + "' and language is null"; - } else { - query_string = "select audio from " + table + " where application='conference' and message='" + message + "' and language='" + language + "'"; - } - - DBG("Query string <%s>\n", query_string.c_str()); + DBG("Query string <%s>\n", query_string.c_str()); - query << query_string; - mysqlpp::Result res = query.store(); + query << query_string; + mysqlpp::Result res = query.store(); - mysqlpp::Row row; + mysqlpp::Row row; - if (res) { - if ((res.num_rows() > 0) && (row = res.at(0))) { - FILE *file; - unsigned long length = row.raw_string(0).size(); - file = fopen((*audio_file).c_str(), "wb"); - fwrite(row.at(0).data(), 1, length, file); - fclose(file); - return 1; - } else { - *audio_file = ""; - return 1; - } + if (res) { + if ((res.num_rows() > 0) && (row = res.at(0))) { + FILE *file; + unsigned long length = row.raw_string(0).size(); + file = fopen((*audio_file).c_str(), "wb"); + fwrite(row.at(0).data(), 1, length, file); + fclose(file); + return 1; } else { - ERROR("Database query error\n"); - return 0; + *audio_file = ""; + return 1; } - } - - catch (const mysqlpp::Exception& er) { - // Catch-all for any MySQL++ exceptions - ERROR("MySQL++ error: %s\n", er.what()); + } else { + ERROR("Database query error\n"); + *audio_file = ""; return 0; } } + + catch (const mysqlpp::Exception& er) { + // Catch-all for any MySQL++ exceptions + ERROR("MySQL++ error: %s\n", er.what()); + *audio_file = ""; + return 0; + } } int ConferenceFactory::onLoad() @@ -195,7 +184,7 @@ int ConferenceFactory::onLoad() return -1; } - if (!cache_audio_file(LONELY_USER_MSG, "", "", &LonelyUserFile)) { + if (!get_audio_file(LONELY_USER_MSG, "", "", &LonelyUserFile)) { return -1; } @@ -205,11 +194,11 @@ int ConferenceFactory::onLoad() return -1; } - if (!cache_audio_file(JOIN_SOUND, "", "", &JoinSound)) { + if (!get_audio_file(JOIN_SOUND, "", "", &JoinSound)) { return -1; } - if (!cache_audio_file(DROP_SOUND, "", "", &DropSound)) { + if (!get_audio_file(DROP_SOUND, "", "", &DropSound)) { return -1; } @@ -350,13 +339,13 @@ void ConferenceDialog::onSessionStart(const AmSipRequest& req) #ifdef USE_MYSQL /* Get domain/language specific lonely user file from MySQL */ - if (cache_audio_file(LONELY_USER_MSG, req.domain, language, - &lonely_user_file) && + if (get_audio_file(LONELY_USER_MSG, req.domain, language, + &lonely_user_file) && !lonely_user_file.empty()) { ConferenceFactory::LonelyUserFile = lonely_user_file; } else { - if (cache_audio_file(LONELY_USER_MSG, "", language, - &lonely_user_file) && + if (get_audio_file(LONELY_USER_MSG, "", language, + &lonely_user_file) && !lonely_user_file.empty()) { ConferenceFactory::LonelyUserFile = lonely_user_file; } diff --git a/apps/conference/Makefile b/apps/conference/Makefile index 719b28b5..31faffe7 100644 --- a/apps/conference/Makefile +++ b/apps/conference/Makefile @@ -3,7 +3,7 @@ plug_in_name = conference module_ldflags = module_cflags = -# Uncomment following lines if you want to keep audio in MySQL database. +# Uncomment last two lines if you want to keep audio in MySQL database. # You must also install MySQL++ development files and libraries # (http://www.tangentsoft.net/mysql++/). If your MySQL++ version is older # than 2.2, you must insert diff --git a/apps/voicemail/AnswerMachine.cpp b/apps/voicemail/AnswerMachine.cpp index 15aa896b..9376ff29 100644 --- a/apps/voicemail/AnswerMachine.cpp +++ b/apps/voicemail/AnswerMachine.cpp @@ -37,6 +37,21 @@ #include "sems.h" #include "log.h" +#ifdef USE_MYSQL +#include +#include +#include +#include +#define DEFAULT_TEMPLATE_TABLE "default_template" +#define DOMAIN_TEMPLATE_TABLE "domain_template" +#define DEFAULT_AUDIO_TABLE "default_audio" +#define DOMAIN_AUDIO_TABLE "domain_audio" +#define USER_AUDIO_TABLE "user_audio" +#define GREETING_MSG "greeting_msg" +#define BEEP_SOUND "beep_snd" +#define EMAIL_TMPL "email_tmpl" +#endif + #include #include @@ -61,6 +76,184 @@ string AnswerMachineFactory::DefaultAnnounce; int AnswerMachineFactory::MaxRecordTime; AmDynInvokeFactory* AnswerMachineFactory::UserTimer=0; +#ifdef USE_MYSQL +mysqlpp::Connection AnswerMachineFactory::Connection(mysqlpp::use_exceptions); + +int get_audio_file(string message, string domain, string user, + string language, string *audio_file) +{ + string query_string; + + if (!user.empty()) { + *audio_file = string("/tmp/") + domain + "_" + user + "_" + + MOD_NAME + "_" + message + ".wav"; + query_string = "select audio from " + string(USER_AUDIO_TABLE) + " where application='" + MOD_NAME + "' and message='" + message + "' and domain='" + domain + "' and userid='" + user + "'"; + } else { + if (language.empty()) { + if (domain.empty()) { + *audio_file = string("/tmp/") + MOD_NAME + "_" + message + + ".wav"; + query_string = "select audio from " + string(DEFAULT_AUDIO_TABLE) + " where application='" + MOD_NAME + "' and message='" + message + "' and language is null"; + } else { + *audio_file = string("/tmp/") + domain + "_" + MOD_NAME + + "_" + message + ".wav"; + query_string = "select audio from " + string(DOMAIN_AUDIO_TABLE) + " where application='" + MOD_NAME + "' and message='" + message + "' and domain='" + domain + "' and language is null"; + } + } else { + if (domain.empty()) { + *audio_file = string("/tmp/") + MOD_NAME + "_" + message + + "_" + language + ".wav"; + query_string = "select audio from " + string(DEFAULT_AUDIO_TABLE) + " where application='" + MOD_NAME + "' and message='" + message + "' and language='" + language + "'"; + } else { + *audio_file = string("/tmp/") + domain + "_" + MOD_NAME + "_" + + message + "_" + language + ".wav"; + query_string = "select audio from " + string(DOMAIN_AUDIO_TABLE) + " where application='" + MOD_NAME + "' and message='" + message + "' and domain='" + domain + "' and language='" + language + "'"; + } + } + } + + try { + + mysqlpp::Query query = AnswerMachineFactory::Connection.query(); + + DBG("Query string <%s>\n", query_string.c_str()); + + query << query_string; + mysqlpp::Result res = query.store(); + + mysqlpp::Row row; + + if (res) { + if ((res.num_rows() > 0) && (row = res.at(0))) { + FILE *file; + unsigned long length = row.raw_string(0).size(); + file = fopen((*audio_file).c_str(), "wb"); + fwrite(row.at(0).data(), 1, length, file); + fclose(file); + return 1; + } else { + *audio_file = ""; + return 1; + } + } else { + ERROR("Database query error\n"); + *audio_file = ""; + return 0; + } + } + + catch (const mysqlpp::Exception& er) { + // Catch-all for any MySQL++ exceptions + ERROR("MySQL++ error: %s\n", er.what()); + *audio_file = ""; + return 0; + } +} + +int AnswerMachineFactory::loadEmailTemplatesFromMySQL() +{ + + try { + + mysqlpp::Query query = AnswerMachineFactory::Connection.query(); + + string query_string, table; + query_string = "select replace(template, '\r', '') as template, language from " + string(DEFAULT_TEMPLATE_TABLE) + " where application='" + MOD_NAME + "' and message='" + EMAIL_TMPL + "'"; + + DBG("Query string <%s>\n", query_string.c_str()); + + query << query_string; + mysqlpp::Result res = query.store(); + + mysqlpp::Row::size_type i; + mysqlpp::Row::size_type row_count = res.num_rows(); + mysqlpp::Row row; + + for (i = 0; i < row_count; i++) { + row = res.at(i); + FILE *file; + unsigned long length = row["template"].size(); + string tmp_file, tmpl_name; + row = res.at(i); + if (string(row["language"]) == "NULL") { + tmp_file = "/tmp/voicemail_email.template"; + tmpl_name = DEFAULT_MAIL_TMPL; + } else { + tmp_file = string("/tmp/voicemail_email_") + + string(row["language"]) + ".template"; + tmpl_name = DEFAULT_MAIL_TMPL + "_" + + string(row["language"]); + } + file = fopen(tmp_file.c_str(), "wb"); + fwrite(row["template"], 1, length, file); + fclose(file); + DBG("loading %s as %s ...\n", tmp_file.c_str(), tmpl_name.c_str()); + EmailTemplate tmp_tmpl; + if (tmp_tmpl.load(tmp_file)) { + ERROR("Voicemail: could not load default" + " email template: '%s'\n", tmp_file.c_str()); + return -1; + } else { + email_tmpl[tmpl_name] = tmp_tmpl; + } + } + if (email_tmpl.count(DEFAULT_MAIL_TMPL) == 0) { + ERROR("Voicemail: default email template does not exist\n"); + return -1; + } + + query_string = "select domain, replace(template, '\r', '') as template, language from " + string(DOMAIN_TEMPLATE_TABLE) + " where application='" + MOD_NAME +"' and message='" + EMAIL_TMPL + "'"; + + DBG("Query string <%s>\n", query_string.c_str()); + + query << query_string; + res = query.store(); + + row_count = res.num_rows(); + + for (i = 0; i < row_count; i++) { + row = res.at(i); + FILE *file; + unsigned long length = row["template"].size(); + string tmp_file, tmpl_name; + row = res.at(i); + if (string(row["language"]) == "NULL") { + tmp_file = "/tmp/" + string(row["domain"]) + + "_voicemail_email.template"; + tmpl_name = string(row["domain"]); + } else { + tmp_file = string("/tmp/") + string(row["domain"]) + + "_voicemail_email_" + string(row["language"]) + + ".template"; + tmpl_name = string(row["domain"]) + "_" + + string(row["language"]); + } + file = fopen(tmp_file.c_str(), "wb"); + fwrite(row["template"], 1, length, file); + fclose(file); + DBG("loading %s as %s ...\n",tmp_file.c_str(), tmpl_name.c_str()); + EmailTemplate tmp_tmpl; + if (tmp_tmpl.load(tmp_file) < 0) { + ERROR("Voicemail: could not load default" + " email template: '%s'\n", tmp_file.c_str()); + return -1; + } else { + email_tmpl[tmpl_name] = tmp_tmpl; + } + } + } + + catch (const mysqlpp::Exception& er) { + // Catch-all for any MySQL++ exceptions + ERROR("MySQL++ error: %s\n", er.what()); + return -1; + } + + return 0; +} + +#else + int AnswerMachineFactory::loadEmailTemplates(const string& path) { string email_tmpl_file = add2path(path, 1, @@ -113,6 +306,8 @@ int AnswerMachineFactory::loadEmailTemplates(const string& path) return err; } +#endif + int AnswerMachineFactory::onLoad() { AmConfigReader cfg; @@ -122,16 +317,72 @@ int AnswerMachineFactory::onLoad() // get application specific global parameters configureModule(cfg); - AnnouncePath = cfg.getParameter("announce_path",ANNOUNCE_PATH); - DefaultAnnounce = cfg.getParameter("default_announce",DEFAULT_ANNOUNCE); - MaxRecordTime = cfg.getParameterInt("max_record_time",DEFAULT_RECORD_TIME); - RecFileExt = cfg.getParameter("rec_file_ext",DEFAULT_AUDIO_EXT); +#ifdef USE_MYSQL + + /* Get email templates from MySQL */ + + string mysql_server, mysql_user, mysql_passwd, mysql_db; + + mysql_server = cfg.getParameter("mysql_server"); + if (mysql_server.empty()) { + mysql_server = "localhost"; + } + + mysql_user = cfg.getParameter("mysql_user"); + if (mysql_user.empty()) { + ERROR("voicemail.conf paramater 'mysql_user' is missing.\n"); + return -1; + } + + mysql_passwd = cfg.getParameter("mysql_passwd"); + if (mysql_passwd.empty()) { + ERROR("voicemail.conf paramater 'mysql_passwd' is missing.\n"); + return -1; + } + + mysql_db = cfg.getParameter("mysql_db"); + if (mysql_db.empty()) { + mysql_db = "sems"; + } + + try { + + Connection.connect(mysql_db.c_str(), mysql_server.c_str(), + mysql_user.c_str(), mysql_passwd.c_str()); + if (!Connection) { + ERROR("Database connection failed: %s\n", Connection.error()); + return -1; + } + } + + catch (const mysqlpp::Exception& er) { + // Catch-all for any MySQL++ exceptions + ERROR("MySQL++ error: %s\n", er.what()); + return -1; + } + + if(loadEmailTemplatesFromMySQL()){ + ERROR("while loading email templates from MySQL\n"); + return -1; + } + +#else + + /* Get email templates from file system */ if(loadEmailTemplates(cfg.getParameter("email_template_path",DEFAULT_MAIL_TMPL_PATH))){ ERROR("while loading email templates\n"); return -1; } + AnnouncePath = cfg.getParameter("announce_path",ANNOUNCE_PATH); + DefaultAnnounce = cfg.getParameter("default_announce",DEFAULT_ANNOUNCE); + +#endif + + MaxRecordTime = cfg.getParameterInt("max_record_time",DEFAULT_RECORD_TIME); + RecFileExt = cfg.getParameter("rec_file_ext",DEFAULT_AUDIO_EXT); + UserTimer = AmPlugIn::instance()->getFactory4Di("user_timer"); if(!UserTimer){ @@ -166,7 +417,34 @@ AmSession* AnswerMachineFactory::onInvite(const AmSipRequest& req) DBG("email address for user '%s': <%s> \n", req.user.c_str(),email.c_str()); DBG("language: <%s> \n", language.c_str()); - + +#ifdef USE_MYSQL + + string announce_file; + + if (get_audio_file(GREETING_MSG, req.domain, req.user, "", + &announce_file) && !announce_file.empty()) + goto announce_found; + + if (!language.empty()) { + if (get_audio_file(GREETING_MSG, req.domain, "", language, + &announce_file) && !announce_file.empty()) + goto announce_found; + } else { + if (get_audio_file(GREETING_MSG, req.domain, "", "", + &announce_file) && !announce_file.empty()) + goto announce_found; + } + + if (!language.empty()) + if (get_audio_file(GREETING_MSG, "", "", language, + &announce_file) && !announce_file.empty()) + goto announce_found; + + get_audio_file(GREETING_MSG, "", "", "", &announce_file); + +#else + string announce_file = add2path(AnnouncePath,2, req.domain.c_str(), (req.user + ".wav").c_str()); if (file_exists(announce_file)) goto announce_found; @@ -187,6 +465,8 @@ AmSession* AnswerMachineFactory::onInvite(const AmSipRequest& req) if (!file_exists(announce_file)) announce_file = ""; +#endif + announce_found: if(announce_file.empty()) throw AmSession::Exception(500,"voicemail: no greeting file found"); @@ -307,9 +587,19 @@ void AnswerMachineDialog::onSessionStart(const AmSipRequest& req) // disable DTMF detection - don't use DTMF here setDtmfDetectionEnabled(false); - if(a_greeting.open(announce_file.c_str(),AmAudioFile::Read) || +#ifdef USE_MYSQL + string beep_file; + if (!get_audio_file(BEEP_SOUND, "", "", "", &beep_file) || + beep_file.empty()) + throw string("AnswerMachine: could not find beep file\n"); + if (a_greeting.open(announce_file.c_str(),AmAudioFile::Read) || + a_beep.open(beep_file,AmAudioFile::Read)) + throw string("AnswerMachine: could not open greeting or beep file\n"); +#else + if (a_greeting.open(announce_file.c_str(),AmAudioFile::Read) || a_beep.open(add2path(AnswerMachineFactory::AnnouncePath,1, "beep.wav"),AmAudioFile::Read)) throw string("AnswerMachine: could not open annoucement files\n"); +#endif msg_filename = "/tmp/" + getLocalTag() + "." + AnswerMachineFactory::RecFileExt; diff --git a/apps/voicemail/AnswerMachine.h b/apps/voicemail/AnswerMachine.h index eb926280..3aef54da 100644 --- a/apps/voicemail/AnswerMachine.h +++ b/apps/voicemail/AnswerMachine.h @@ -28,6 +28,10 @@ #ifndef _ANSWERMACHINE_H_ #define _ANSWERMACHINE_H_ +#ifdef USE_MYSQL +#include +#endif + #include "AmSession.h" #include "AmConfigReader.h" #include "EmailTemplate.h" @@ -44,7 +48,12 @@ class AnswerMachineFactory: public AmSessionFactory map email_tmpl; int getEmailAddress(); + +#ifdef USE_MYSQL + int loadEmailTemplatesFromMySQL(); +#else int loadEmailTemplates(const string& path); +#endif public: static string RecFileExt; @@ -53,6 +62,9 @@ public: static int MaxRecordTime; static AmDynInvokeFactory* UserTimer; +#ifdef USE_MYSQL + static mysqlpp::Connection Connection; +#endif AnswerMachineFactory(const string& _app_name); diff --git a/apps/voicemail/Makefile b/apps/voicemail/Makefile index c668cb73..83c66ba4 100644 --- a/apps/voicemail/Makefile +++ b/apps/voicemail/Makefile @@ -3,6 +3,26 @@ plug_in_name = voicemail module_ldflags = module_cflags = +# Uncomment the last two lines if you want to keep templates and audio +# in MySQL database. +# +# You must also install MySQL++ development files and libraries +# (http://www.tangentsoft.net/mysql++/). If your MySQL++ version is older +# than 2.2, you must insert +# +# const std::string & raw_string(int i) const +# { +# return data_[i]; +# } +# +# in /usr/include/mysql++/row.h. +# +# You must manually install default.template.sample to default_template +# database table. +# +#module_ldflags = -lmysqlpp +#module_cflags = -DUSE_MYSQL -I/usr/include/mysql++ -I/usr/include/mysql + extra_install = install_email_template $(plug_in_name)_audio vm_module: all diff --git a/apps/voicemail/etc/voicemail.conf b/apps/voicemail/etc/voicemail.conf index 9aede97e..d623e1c2 100644 --- a/apps/voicemail/etc/voicemail.conf +++ b/apps/voicemail/etc/voicemail.conf @@ -1,3 +1,5 @@ +# These are needed if you keep audio and template files in file system: + #CFGOPTION_SEMS_ANNOUNCEPATH announce_path=/usr/local/lib/sems/audio/voicemail/ #ENDCFGOPTION @@ -6,14 +8,23 @@ announce_path=/usr/local/lib/sems/audio/voicemail/ default_announce=default_en.wav #ENDCFGOPTION -#CFGOPTION_SEMS_RECORDTIME -max_record_time=30 -#ENDCFGOPTION - #CFGOPTION_SEMS_TEMPLATEDIR email_template_path=/usr/local/etc/sems/ #ENDCFGOPTION +# These are needed if you keep audio and template files in MySQL database: + +#mysql_host=localhost +#mysql_user=sems +#mysql_passwd=sems +#mysql_db=sems + +# These are independent on where audio and template files are kept: + +#CFGOPTION_SEMS_RECORDTIME +max_record_time=30 +#ENDCFGOPTION + # rec_file_ext : extension to recorded file, determines file # format (wav, mp3; need mp3 plugin loaded for mp3) # default is 'wav' diff --git a/doc/Readme.conference b/doc/Readme.conference index 0e18c69c..83389ec7 100644 --- a/doc/Readme.conference +++ b/doc/Readme.conference @@ -92,10 +92,10 @@ CREATE TABLE domain_audio ( The first one stores default audio files and the latter domain specific audio files. Application value must be 'conference' and message values -are 'first_participant_msg', 'join_sound', and 'drop_sound'. +are 'first_participant_msg', 'join_snd', and 'drop_snd'. -When an audio file is fetched from database, it is cached in /tmp -directory and later on fetched from there. +When an audio file is fetched from database, it is stored in /tmp +directory. These are independent of audio storage: diff --git a/doc/Readme.voicemail b/doc/Readme.voicemail index f93606f1..98846a7f 100644 --- a/doc/Readme.voicemail +++ b/doc/Readme.voicemail @@ -3,8 +3,14 @@ voicemail (voicemail2email) application This application plays a greeting message to the caller, records a voicemail and sends it out as email via SMTP. -The voicemail application looks in various paths for the greeting -message to be played, the first file found will be played: +Audio Files +----------- + +The voicemail application looks in various file system paths or database +tables for announce and beep messages to be played. + +If file system is used to store audio files, the announcement file to be +played is looked for in the following order: '.wav' @@ -16,18 +22,41 @@ where and is set in voicemail.conf, is the host part of the request URI, the user part of the request URI, and is the App-Param 'Language' (see below). -If you have a small application record or copy the greeting to -'.wav' it will be played back instead of the -default announcement. +If MySQL database is used to store audio files, the announcement to be +played is looked for first from user_audio table, then from domain_audio +table, and last from default_audio table. The last two tables are +defined as described in Readme.conference. user_audio table is defined +as follows: + +CREATE TABLE user_audio ( + id int(10) unsigned NOT NULL auto_increment, + application varchar(32) NOT NULL, + message varchar(32) NOT NULL, + domain varchar(128) NOT NULL, + userid varchar(64) NOT NULL, + audio mediumblob NOT NULL, + PRIMARY KEY (id), + UNIQUE KEY application (application,message,domain,userid) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + +Beep sound to be played is looked for only from default_audio table. + +Application value is 'voicemail' and message values are 'greeting_msg' +and 'beep_snd'. -The format of the email can be configured using email templates -(see below). +When an audio file is fetched from database, it is stored in /tmp +directory. + +Mail Server +----------- The mail server to send the email with is configured in the main sems.conf in smtp_server/smtp_port. +Other Items +----------- -further configuration items (voicemail.conf): +Further configuration items (voicemail.conf): max_record_time - voicemail records voicemail up to the number of seconds set here @@ -58,15 +87,16 @@ SEMS knows at least the email address to send the email to. Voicemail email templates ------------------------- -Email templates will help you to customize the emails -sent by Voicemail. Just configure the path where the -templates can be found and edit your template files. -You will find detailed informations in the following +The format of the email can be configured using email templates. Email +templates will help you to customize the emails sent by Voicemail. Just +configure the path where the templates can be found and edit your +template files. You will find detailed informations in the following sections. - Configuration parameters within voicemail.conf: --------------------------------------------------- +---------------------------------------------- + +This is needed in template files are kept in file system: email_template_path: @@ -88,7 +118,33 @@ on, you should find in the log file during loading process following lines: (9834) DEBUG: loadEmailTemplates (AnswerMachine.cpp:102): loading plug-in/voicemail/iptel.org.template ... (9834) DEBUG: loadEmailTemplates (AnswerMachine.cpp:102): loading plug-in/voicemail/susie.at.template ... - +If template files are kept in MySQL database, they are looked for first +from domain_template table and then from default_template table, which +are defined as follows: + +CREATE TABLE domain_template ( + id int(10) unsigned NOT NULL, + application varchar(32) NOT NULL, + message varchar(32) NOT NULL, + domain varchar(128) NOT NULL, + `language` char(2) default NULL, + template text NOT NULL, + PRIMARY KEY (id) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + +CREATE TABLE default_template ( + id int(10) unsigned NOT NULL auto_increment, + application varchar(32) NOT NULL, + message varchar(32) NOT NULL, + `language` char(2) default NULL, + template text NOT NULL, + PRIMARY KEY (id) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + +Application value is 'voicemail' and message value is 'email_tmpl'. + +When an audio file is fetched from database, it is stored in /tmp +directory. Email template format: ---------------------- @@ -123,4 +179,3 @@ Following variables are supported: - %from% : remote URI. - %from_user% : remote user. - %from_domain% : remote domain. -