Author: sayer
Date: 2008-05-15 16:32:07 +0200 (Thu, 15 May 2008)
New Revision: 962
Added:
trunk/apps/annrecorder/
trunk/apps/annrecorder/AnnRecorder.cpp
trunk/apps/annrecorder/AnnRecorder.h
trunk/apps/annrecorder/Makefile
trunk/apps/annrecorder/etc/
trunk/apps/annrecorder/etc/annrecorder.conf
trunk/apps/annrecorder/wav/
trunk/apps/annrecorder/wav/beep.wav
trunk/apps/annrecorder/wav/bye.wav
trunk/apps/annrecorder/wav/confirm.wav
trunk/apps/annrecorder/wav/greeting_set.wav
trunk/apps/annrecorder/wav/to_record.wav
trunk/apps/annrecorder/wav/welcome.wav
trunk/apps/annrecorder/wav/your_prompt.wav
Log:
application to record a personal away message with ivr menu, msg_storage etc
Added: trunk/apps/annrecorder/AnnRecorder.cpp
===================================================================
--- trunk/apps/annrecorder/AnnRecorder.cpp 2008-05-15 14:31:30 UTC (rev
961)
+++ trunk/apps/annrecorder/AnnRecorder.cpp 2008-05-15 14:32:07 UTC (rev
962)
@@ -0,0 +1,524 @@
+/*
+ * $Id: AnnRecorder.cpp 722 2008-02-12 12:52:31Z sayer $
+ *
+ * Copyright (C) 2002-2003 Fhg Fokus
+ *
+ * This file is part of sems, a free SIP media server.
+ *
+ * sems 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.
+ *
+ * For a license to use the sems software under conditions
+ * other than those described here, or to purchase support for this
+ * software, please contact iptel.org by e-mail at the following addresses:
+ * [EMAIL PROTECTED]
+ *
+ * sems 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
+ */
+
+#include "AnnRecorder.h"
+#include "AmConfig.h"
+#include "AmUtils.h"
+#include "AmPlugIn.h"
+#include "AmPromptCollection.h"
+#include "../msg_storage/MsgStorageAPI.h"
+#include "sems.h"
+#include "log.h"
+
+using std::map;
+
+#define MOD_NAME "annrecorder"
+
+#define DEFAULT_TYPE "aa"
+#define DOMAIN_PROMPT_SUFFIX "-prompt"
+
+#define TIMERID_START_TIMER 1
+#define TIMERID_CONFIRM_TIMER 2
+
+#define START_RECORDING_TIMEOUT 20
+#define CONFIRM_RECORDING_TIMEOUT 20
+
+#define SEP_CONFIRM_BEGIN 1
+#define SEP_MSG_BEGIN 2
+
+#define MAX_MESSAGE_TIME 120
+
+EXPORT_SESSION_FACTORY(AnnRecorderFactory,MOD_NAME);
+
+string AnnRecorderFactory::AnnouncePath;
+string AnnRecorderFactory::DefaultAnnounce;
+AmDynInvokeFactory* AnnRecorderFactory::user_timer_fact = NULL;
+AmDynInvokeFactory* AnnRecorderFactory::message_storage_fact = NULL;
+
+const char* MsgStrError(int e) {
+ switch (e) {
+ case MSG_OK: return "MSG_OK"; break;
+ case MSG_EMSGEXISTS: return "MSG_EMSGEXISTS"; break;
+ case MSG_EUSRNOTFOUND: return "MSG_EUSRNOTFOUND"; break;
+ case MSG_EMSGNOTFOUND: return "MSG_EMSGNOTFOUND"; break;
+ case MSG_EALREADYCLOSED: return "MSG_EALREADYCLOSED"; break;
+ case MSG_EREADERROR: return "MSG_EREADERROR"; break;
+ case MSG_ENOSPC: return "MSG_ENOSPC"; break;
+ case MSG_ESTORAGE: return "MSG_ESTORAGE"; break;
+ default: return "Unknown Error";
+ }
+}
+
+AnnRecorderFactory::AnnRecorderFactory(const string& _app_name)
+ : AmSessionFactory(_app_name)
+{
+}
+
+int AnnRecorderFactory::onLoad()
+{
+ AmConfigReader cfg;
+ if(cfg.loadFile(AmConfig::ModConfigPath + string(MOD_NAME ".conf")))
+ return -1;
+
+ // get application specific global parameters
+ configureModule(cfg);
+
+ AnnouncePath = cfg.getParameter("announce_path",ANNOUNCE_PATH);
+ if( !AnnouncePath.empty()
+ && AnnouncePath[AnnouncePath.length()-1] != '/' )
+ AnnouncePath += "/";
+ DefaultAnnounce = cfg.getParameter("default_announce");
+
+ AM_PROMPT_START;
+ AM_PROMPT_ADD(WELCOME, ANNREC_ANNOUNCE_PATH WELCOME".wav");
+ AM_PROMPT_ADD(YOUR_PROMPT, ANNREC_ANNOUNCE_PATH YOUR_PROMPT".wav");
+ AM_PROMPT_ADD(TO_RECORD, ANNREC_ANNOUNCE_PATH TO_RECORD".wav");
+ AM_PROMPT_ADD(CONFIRM, ANNREC_ANNOUNCE_PATH CONFIRM".wav");
+ AM_PROMPT_ADD(GREETING_SET, ANNREC_ANNOUNCE_PATH GREETING_SET".wav");
+ AM_PROMPT_ADD(BYE, ANNREC_ANNOUNCE_PATH BYE".wav");
+ AM_PROMPT_ADD(BEEP, ANNREC_ANNOUNCE_PATH BEEP".wav");
+ AM_PROMPT_END(prompts, cfg, MOD_NAME);
+
+
+ user_timer_fact = AmPlugIn::instance()->getFactory4Di("user_timer");
+ if(!user_timer_fact) {
+ ERROR("sorry, could not load user_timer from session_timer plug-in\n");
+ return -1;
+ }
+
+ message_storage_fact= AmPlugIn::instance()->getFactory4Di("msg_storage");
+ if(!user_timer_fact) {
+ ERROR("sorry, could not get msg_storage, please load a suitable
plug-in\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+void AnnRecorderFactory::getAppParams(const AmSipRequest& req, map<string,
string>& params) {
+ string language;
+ string domain;
+ string user;
+ string typ;
+
+ string iptel_app_param = getHeader(req.hdrs, PARAM_HDR);
+
+ if (!iptel_app_param.length()) {
+ throw AmSession::Exception(500, MOD_NAME ": parameters not found");
+ }
+
+ language = get_header_keyvalue(iptel_app_param, "lng", "Language");
+
+ user = get_header_keyvalue(iptel_app_param,"usr", "User");
+ if (!user.length())
+ user = req.user;
+
+ domain = get_header_keyvalue(iptel_app_param, "dom", "Domain");
+ if (!domain.length())
+ domain = req.domain;
+
+
+ typ = get_header_keyvalue(iptel_app_param, "typ", "Type");
+ if (!typ.length())
+ typ = DEFAULT_TYPE;
+
+ // checks
+ if (user.empty())
+ throw AmSession::Exception(500, MOD_NAME ": user missing");
+
+ string announce_file = add2path(AnnouncePath,2, domain.c_str(), (user +
".wav").c_str());
+ if (file_exists(announce_file)) goto announce_found;
+
+ if (!language.empty()) {
+ announce_file = add2path(AnnouncePath,3, domain.c_str(), language.c_str(),
DefaultAnnounce.c_str());
+ if (file_exists(announce_file)) goto announce_found;
+ }
+
+ announce_file = add2path(AnnouncePath,2, domain.c_str(),
DefaultAnnounce.c_str());
+ if (file_exists(announce_file)) goto announce_found;
+
+ if (!language.empty()) {
+ announce_file = add2path(AnnouncePath,2, language.c_str(),
DefaultAnnounce.c_str());
+ if (file_exists(announce_file)) goto announce_found;
+ }
+
+ announce_file = add2path(AnnouncePath,1, DefaultAnnounce.c_str());
+ if (!file_exists(announce_file))
+ announce_file = "";
+
+ announce_found:
+
+ DBG(MOD_NAME " invocation parameters: \n");
+ DBG(" User: <%s> \n", user.c_str());
+ DBG(" Domain: <%s> \n", domain.c_str());
+ DBG(" Language: <%s> \n", language.c_str());
+ DBG(" Type: <%s> \n", typ.c_str());
+ DBG(" Def. File:<%s> \n", announce_file.c_str());
+
+ params["domain"] = domain;
+ params["user"] = user;
+ params["defaultfile"] = announce_file;
+ params["type"] = typ;
+}
+
+AmSession* AnnRecorderFactory::onInvite(const AmSipRequest& req)
+{
+ map<string, string> params;
+ getAppParams(req, params);
+ return new AnnRecorderDialog(params, prompts, NULL);
+}
+
+AmSession* AnnRecorderFactory::onInvite(const AmSipRequest& req,
+ AmArg& session_params)
+{
+ UACAuthCred* cred = NULL;
+ if (session_params.getType() == AmArg::AObject) {
+ ArgObject* cred_obj = session_params.asObject();
+ if (cred_obj)
+ cred = dynamic_cast<UACAuthCred*>(cred_obj);
+ }
+
+ map<string, string> params;
+ getAppParams(req, params);
+ AmSession* s = new AnnRecorderDialog(params, prompts, cred);
+
+ if (NULL == cred) {
+ WARN("discarding unknown session parameters.\n");
+ } else {
+ AmSessionEventHandlerFactory* uac_auth_f =
+ AmPlugIn::instance()->getFactory4Seh("uac_auth");
+ if (uac_auth_f != NULL) {
+ DBG("UAC Auth enabled for new announcement session.\n");
+ AmSessionEventHandler* h = uac_auth_f->getHandler(s);
+ if (h != NULL )
+ s->addHandler(h);
+ } else {
+ ERROR("uac_auth interface not accessible. "
+ "Load uac_auth for authenticated dialout.\n");
+ }
+ }
+
+ return s;
+}
+
+AnnRecorderDialog::AnnRecorderDialog(const map<string, string>& params,
+ AmPromptCollection& prompts,
+ UACAuthCred* credentials)
+ : params(params),
+ prompts(prompts), cred(credentials),
+ playlist(this)
+{
+ user_timer = AnnRecorderFactory::user_timer_fact->getInstance();
+ if(!user_timer) {
+ ERROR("could not get a user timer reference\n");
+ throw AmSession::Exception(500,"could not get a timer");
+ }
+
+ msg_storage = AnnRecorderFactory::message_storage_fact->getInstance();
+ if(!msg_storage){
+ ERROR("could not get a message storage reference\n");
+ throw AmSession::Exception(500,"could not get a message storage
reference");
+ }
+}
+
+AnnRecorderDialog::~AnnRecorderDialog()
+{
+ prompts.cleanup((long)this);
+ if (msg_filename.length())
+ unlink(msg_filename.c_str());
+}
+
+void AnnRecorderDialog::onSessionStart(const AmSipRequest& req)
+{
+ DBG("AnnRecorderDialog::onSessionStart\n");
+ startSession();
+}
+
+void AnnRecorderDialog::onSessionStart(const AmSipReply& rep)
+{
+ DBG("AnnRecorderDialog::onSessionStart (SEMS originator mode)\n");
+ startSession();
+}
+
+void AnnRecorderDialog::startSession(){
+ prompts.addToPlaylist(WELCOME, (long)this, playlist);
+ prompts.addToPlaylist(YOUR_PROMPT, (long)this, playlist);
+ enqueueCurrent();
+ prompts.addToPlaylist(TO_RECORD, (long)this, playlist);
+ enqueueSeparator(SEP_MSG_BEGIN);
+
+ // set the playlist as input and output
+ setInOut(&playlist,&playlist);
+ state = S_WAIT_START;
+}
+
+void AnnRecorderDialog::enqueueCurrent() {
+ wav_file.close();
+ FILE* fp = getCurrentMessage();
+ if (!fp) {
+ DBG("no recorded msg available, using default\n");
+ if (wav_file.open(params["defaultfile"], AmAudioFile::Read)) {
+ ERROR("opening default greeting file '%s'!\n",
params["defaultfile"].c_str());
+ return;
+ }
+ } else {
+ if (wav_file.fpopen("aa.wav", AmAudioFile::Read, fp)) {
+ ERROR("fpopen message file!\n");
+ return;
+ }
+ }
+ playlist.addToPlaylist(new AmPlaylistItem(&wav_file, NULL));
+}
+
+void AnnRecorderDialog::onDtmf(int event, int duration_msec) {
+ DBG("DTMF %d, %d\n", event, duration_msec);
+ // remove timer
+ try {
+ AmArg di_args,ret;
+ di_args.push(getLocalTag().c_str());
+ user_timer->invoke("removeUserTimers", di_args, ret);
+ } catch(...) {
+ ERROR("Exception caught calling mod api\n");
+ }
+
+ switch (state) {
+ case S_WAIT_START: {
+ DBG("received key %d in state S_WAIT_START: start recording\n", event);
+ playlist.close(false);
+
+ wav_file.close();
+ msg_filename = "/tmp/" + getLocalTag() + ".wav";
+ if(wav_file.open(msg_filename,AmAudioFile::Write,false)) {
+ ERROR("AnnRecorder: couldn't open %s for writing\n",
+ msg_filename.c_str());
+ dlg.bye();
+ setStopped();
+ }
+ wav_file.setRecordTime(MAX_MESSAGE_TIME*1000);
+ prompts.addToPlaylist(BEEP, (long)this, playlist);
+ playlist.addToPlaylist(new AmPlaylistItem(NULL,&wav_file));
+
+ state = S_RECORDING;
+ } break;
+
+ case S_RECORDING: {
+ DBG("received key %d in state S_RECORDING: replay recording\n", event);
+ prompts.addToPlaylist(BEEP, (long)this, playlist);
+ playlist.close(false);
+ replayRecording();
+
+ } break;
+
+ case S_CONFIRM: {
+ DBG("received key %d in state S_CONFIRM save or redo\n", event);
+ playlist.close(false);
+
+ wav_file.close();
+ if (event == 1) {
+ // save msg
+ saveAndConfirm();
+ } else {
+ prompts.addToPlaylist(TO_RECORD, (long)this, playlist);
+ state = S_WAIT_START;
+ }
+ } break;
+
+ default: {
+ DBG("ignoring key %d in state %d\n",
+ event, state);
+ }break;
+ }
+
+}
+
+void AnnRecorderDialog::saveAndConfirm() {
+// wav_file.setCloseOnDestroy(false);
+// wav_file.on_close();
+ saveMessage(wav_file.getfp());
+ prompts.addToPlaylist(GREETING_SET, (long)this, playlist);
+ prompts.addToPlaylist(BYE, (long)this, playlist);
+ state = S_BYE;
+}
+
+void AnnRecorderDialog::onBye(const AmSipRequest& req)
+{
+ DBG("onBye: stopSession\n");
+ setStopped();
+}
+
+void AnnRecorderDialog::process(AmEvent* event)
+{
+
+ AmPluginEvent* plugin_event = dynamic_cast<AmPluginEvent*>(event);
+ if(plugin_event && plugin_event->name == "timer_timeout") {
+ event->processed = true;
+ int timer_id = plugin_event->data.get(0).asInt();
+ if (timer_id == TIMERID_START_TIMER) {
+ if (S_WAIT_START == state) {
+ prompts.addToPlaylist(BYE, (long)this, playlist);
+ state = S_BYE;
+ }
+ return;
+ }
+ if (timer_id == TIMERID_CONFIRM_TIMER) {
+ saveAndConfirm();
+ return;
+ }
+ ERROR("unknown timer id!\n");
+ }
+
+ AmAudioEvent* audio_event = dynamic_cast<AmAudioEvent*>(event);
+ if(audio_event && (audio_event->event_id == AmAudioEvent::noAudio)){
+
+ if (S_BYE == state) {
+ dlg.bye();
+ setStopped();
+ return;
+ }
+
+ if (S_RECORDING == state) {
+ replayRecording();
+ }
+ }
+
+ AmPlaylistSeparatorEvent* pl_ev =
dynamic_cast<AmPlaylistSeparatorEvent*>(event);
+ if (pl_ev) {
+ if ((pl_ev->event_id == SEP_MSG_BEGIN) &&
+ (S_WAIT_START == state)) {
+ // start timer
+ AmArg di_args,ret;
+ di_args.push(TIMERID_START_TIMER);
+ di_args.push(START_RECORDING_TIMEOUT); // in seconds
+ di_args.push(getLocalTag().c_str());
+ user_timer->invoke("setTimer", di_args, ret);
+ return;
+ }
+
+ if ((pl_ev->event_id == SEP_CONFIRM_BEGIN) &&
+ (S_CONFIRM == state)) {
+ // start timer
+ AmArg di_args,ret;
+ di_args.push(TIMERID_CONFIRM_TIMER);
+ di_args.push(CONFIRM_RECORDING_TIMEOUT); // in seconds
+ di_args.push(getLocalTag().c_str());
+ user_timer->invoke("setTimer", di_args, ret);
+ return;
+ }
+ return;
+ }
+ AmSession::process(event);
+}
+
+void AnnRecorderDialog::replayRecording() {
+ prompts.addToPlaylist(YOUR_PROMPT, (long)this, playlist);
+ DBG("msg_filename = '%s'\n", msg_filename.c_str());
+ if (!wav_file.open(msg_filename, AmAudioFile::Read))
+ playlist.addToPlaylist(new AmPlaylistItem(&wav_file, NULL));
+ prompts.addToPlaylist(CONFIRM, (long)this, playlist);
+ enqueueSeparator(SEP_CONFIRM_BEGIN);
+ state = S_CONFIRM;
+}
+
+inline UACAuthCred* AnnRecorderDialog::getCredentials() {
+ return cred.get();
+}
+
+void AnnRecorderDialog::saveMessage(FILE* fp) {
+ string msg_name = params["type"]+".wav";
+ DBG("message name is '%s'\n", msg_name.c_str());
+
+ AmArg di_args,ret;
+ di_args.push((params["domain"]+DOMAIN_PROMPT_SUFFIX).c_str()); // domain
+ di_args.push(params["user"].c_str()); // user
+ di_args.push(msg_name.c_str()); // message
name
+ AmArg df;
+ MessageDataFile df_arg(fp);
+ df.setBorrowedPointer(&df_arg);
+ di_args.push(df);
+ try {
+ msg_storage->invoke("msg_new",di_args,ret);
+ } catch(string& s) {
+ ERROR("invoking msg_new: '%s'\n", s.c_str());
+ } catch(...) {
+ ERROR("invoking msg_new.\n");
+ }
+ // TODO: evaluate ret return value
+}
+
+FILE* AnnRecorderDialog::getCurrentMessage() {
+ string msgname = params["type"]+".wav";
+ string& user = params["user"];
+ string domain = params["domain"]+DOMAIN_PROMPT_SUFFIX;
+
+ DBG("trying to get message '%s' for user '%s' domain '%s'\n",
+ msgname.c_str(), user.c_str(), domain.c_str());
+ AmArg di_args,ret;
+ di_args.push(domain.c_str()); // domain
+ di_args.push(user.c_str()); // user
+ di_args.push(msgname.c_str()); // msg name
+
+ msg_storage->invoke("msg_get",di_args,ret);
+ if (!ret.size()
+ || !isArgInt(ret.get(0))) {
+ ERROR("msg_get for user '%s' domain '%s' msg '%s'"
+ " returned no (valid) result.\n",
+ user.c_str(), domain.c_str(),
+ msgname.c_str()
+ );
+ return NULL;
+ }
+ int ecode = ret.get(0).asInt();
+ if (MSG_OK != ecode) {
+ DBG("msg_get for user '%s' domain '%s' message '%s': %s\n",
+ user.c_str(), domain.c_str(),
+ msgname.c_str(),
+ MsgStrError(ret.get(0).asInt()));
+ return NULL;
+ }
+
+ if ((ret.size() < 2) ||
+ (!isArgAObject(ret.get(1)))) {
+ ERROR("msg_get for user '%s' domain '%s' message '%s': "
+ "invalid return value\n",
+ user.c_str(), domain.c_str(),
+ msgname.c_str());
+ return NULL;
+ }
+ MessageDataFile* f =
+ dynamic_cast<MessageDataFile*>(ret.get(1).asObject());
+ if (NULL == f)
+ return NULL;
+
+ FILE* fp = f->fp;
+ delete f;
+ return fp;
+}
+
+void AnnRecorderDialog::enqueueSeparator(int id) {
+ playlist_separator.reset(new AmPlaylistSeparator(this, id));
+ playlist.addToPlaylist(new AmPlaylistItem(playlist_separator.get(), NULL));
+}
Added: trunk/apps/annrecorder/AnnRecorder.h
===================================================================
--- trunk/apps/annrecorder/AnnRecorder.h 2008-05-15 14:31:30 UTC (rev
961)
+++ trunk/apps/annrecorder/AnnRecorder.h 2008-05-15 14:32:07 UTC (rev
962)
@@ -0,0 +1,141 @@
+/*
+ * $Id: AnnRecorder.h 711 2008-02-10 18:52:44Z sayer $
+ *
+ * Copyright (C) 2002-2003 Fhg Fokus
+ *
+ * This file is part of sems, a free SIP media server.
+ *
+ * sems 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.
+ *
+ * For a license to use the sems software under conditions
+ * other than those described here, or to purchase support for this
+ * software, please contact iptel.org by e-mail at the following addresses:
+ * [EMAIL PROTECTED]
+ *
+ * sems 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
+ */
+
+#ifndef _ANNRECORDER_H_
+#define _ANNRECORDER_H_
+
+#include "AmSession.h"
+#include "AmAudioFile.h"
+#include "AmConfigReader.h"
+
+#include "ampi/UACAuthAPI.h"
+
+#include "AmPromptCollection.h"
+
+#include <string>
+using std::string;
+#include <map>
+
+#include <memory>
+
+// prompts used
+
+//"Welcome to iptel dot org voip service."
+#define WELCOME "welcome"
+// "Your auto attendant greeting sounds like this: -"
+#define YOUR_PROMPT "your_prompt"
+// "To record a new auto attendant greeting, press any key. End recording with
any key. -"
+#define TO_RECORD "to_record"
+//"Press one to keep the new greeting, or two to record a new one. -"
+#define CONFIRM "confirm"
+// "Your new auto attendant greeting has been set."
+#define GREETING_SET "greeting_set"
+// "Thank you for using the iptel dot org service. Good Bye. - "
+#define BYE "bye"
+#define BEEP "beep"
+
+#define ANNREC_ANNOUNCE_PATH "/usr/local/lib/sems/audio/annrecorder/"
+
+/** \brief Factory for announcement sessions */
+class AnnRecorderFactory: public AmSessionFactory
+{
+ void getAppParams(const AmSipRequest& req, std::map<string, string>& params);
+ AmPromptCollection prompts;
+
+public:
+ static AmDynInvokeFactory* user_timer_fact;
+ static AmDynInvokeFactory* message_storage_fact;
+
+ static string AnnouncePath;
+ static string DefaultAnnounce;
+
+ AnnRecorderFactory(const string& _app_name);
+
+ int onLoad();
+ AmSession* onInvite(const AmSipRequest& req);
+ AmSession* onInvite(const AmSipRequest& req,
+ AmArg& session_params);
+
+};
+
+/**\brief announcement session logic implementation */
+class AnnRecorderDialog : public AmSession,
+ public CredentialHolder
+{
+ AmPromptCollection& prompts;
+ AmPlaylist playlist;
+ // we need only one separator in queue
+ auto_ptr<AmPlaylistSeparator> playlist_separator;
+
+ AmAudioFile wav_file;
+ std::map<string, string> params;
+
+ string msg_filename; // recorded file
+
+ AmDynInvoke* user_timer;
+ AmDynInvoke* msg_storage;
+
+ std::auto_ptr<UACAuthCred> cred;
+
+ enum AnnRecorderState {
+ S_WAIT_START,
+ S_BYE,
+ S_RECORDING,
+ S_CONFIRM
+ };
+
+ AnnRecorderState state;
+ void enqueueCurrent();
+ void saveAndConfirm();
+ void replayRecording();
+ void enqueueSeparator(int id);
+
+ FILE* getCurrentMessage();
+ void saveMessage(FILE* fp);
+
+public:
+ AnnRecorderDialog(const std::map<string, string>& params,
+ AmPromptCollection& prompts,
+ UACAuthCred* credentials = NULL);
+ ~AnnRecorderDialog();
+
+ void onSessionStart(const AmSipRequest& req);
+ void onSessionStart(const AmSipReply& rep);
+ void startSession();
+ void onBye(const AmSipRequest& req);
+ void onDtmf(int event, int duration_msec);
+
+ void process(AmEvent* event);
+
+ UACAuthCred* getCredentials();
+};
+
+#endif
+// Local Variables:
+// mode:C++
+// End:
+
Added: trunk/apps/annrecorder/Makefile
===================================================================
--- trunk/apps/annrecorder/Makefile 2008-05-15 14:31:30 UTC (rev 961)
+++ trunk/apps/annrecorder/Makefile 2008-05-15 14:32:07 UTC (rev 962)
@@ -0,0 +1,9 @@
+plug_in_name = annrecorder
+
+module_ldflags =
+module_cflags =
+
+extra_install = $(plug_in_name)_audio
+
+COREPATH ?=../../core
+include $(COREPATH)/plug-in/Makefile.app_module
Added: trunk/apps/annrecorder/etc/annrecorder.conf
===================================================================
--- trunk/apps/annrecorder/etc/annrecorder.conf 2008-05-15 14:31:30 UTC (rev
961)
+++ trunk/apps/annrecorder/etc/annrecorder.conf 2008-05-15 14:32:07 UTC (rev
962)
@@ -0,0 +1,25 @@
+announce_path=/usr/local/lib/sems/audio/
+default_announce=default_en.wav
+beep=/usr/local/lib/sems/audio/beep.wav
+
+# prompts
+
+#"Welcome to iptel dot org voip service."
+welcome=/usr/local/lib/sems/audio/annrecorder/welcome.wav
+
+# "Your auto attendant greeting sounds like this: -"
+your_prompt=/usr/local/lib/sems/audio/annrecorder/your_prompt.wav
+
+# "To record a new auto attendant greeting, press any key.
+# End recording with any key. -"
+to_record=/usr/local/lib/sems/audio/annrecorder/to_record.wav
+
+# "Press one to keep the new greeting, or two to record a new one. -"
+confirm=/usr/local/lib/sems/audio/annrecorder/confirm.wav
+
+# "Your new auto attendant greeting has been set."
+greeting_set=/usr/local/lib/sems/audio/annrecorder/greeting_set.wav
+
+# "Thank you for using the iptel dot org service. Good Bye. - "
+bye=/usr/local/lib/sems/audio/annrecorder/bye.wav
+
Added: trunk/apps/annrecorder/wav/beep.wav
===================================================================
(Binary files differ)
Property changes on: trunk/apps/annrecorder/wav/beep.wav
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/apps/annrecorder/wav/bye.wav
===================================================================
(Binary files differ)
Property changes on: trunk/apps/annrecorder/wav/bye.wav
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/apps/annrecorder/wav/confirm.wav
===================================================================
(Binary files differ)
Property changes on: trunk/apps/annrecorder/wav/confirm.wav
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/apps/annrecorder/wav/greeting_set.wav
===================================================================
(Binary files differ)
Property changes on: trunk/apps/annrecorder/wav/greeting_set.wav
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/apps/annrecorder/wav/to_record.wav
===================================================================
(Binary files differ)
Property changes on: trunk/apps/annrecorder/wav/to_record.wav
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/apps/annrecorder/wav/welcome.wav
===================================================================
(Binary files differ)
Property changes on: trunk/apps/annrecorder/wav/welcome.wav
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/apps/annrecorder/wav/your_prompt.wav
===================================================================
(Binary files differ)
Property changes on: trunk/apps/annrecorder/wav/your_prompt.wav
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
_______________________________________________
Semsdev mailing list
[email protected]
http://lists.iptel.org/mailman/listinfo/semsdev