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

Reply via email to