void ConferenceDialog::closeChannels()
{
  play_list.close();
  setInOut(NULL,NULL);
  channel.reset(NULL);
  dialout_channel.reset(NULL);
}
Beispiel #2
0
void MyCCDialog::onOtherReply(const AmSipReply& reply) {
  DBG("OnOtherReply \n");
  if (state == CC_Dialing) {
    if (reply.code < 200) {
      DBG("Callee is trying... code %d\n", reply.code);
    } else if(reply.code < 300){
      if (getCalleeStatus()  == Connected) {
	state = CC_Connected;
	startAccounting();
	// clear audio input and output
	setInOut(NULL, NULL);
	// detach from media processor (not in RTP path any more)
	AmMediaProcessor::instance()->removeSession(this);
	// set the call timer
	AmArg di_args,ret;
	di_args.push(TIMERID_CREDIT_TIMEOUT);
	di_args.push(credit); // in seconds
	di_args.push(dlg.local_tag.c_str());
	user_timer->invoke("setTimer", di_args, ret);
      }
    } else {
      DBG("Callee final error with code %d\n",reply.code);
      addToPlaylist(MyCCFactory::DialFailed);
      number = "";
      state = CC_Collecting_Number;
    }
  }  
  // we dont call
  //  AmB2BCallerSession::onOtherReply(reply);
  // as it tears down the call if callee could
  // not be reached
}
void PinAuthConferenceDialog::onBye(const AmSipRequest& req)
{
  play_list.close();
  setInOut(NULL,NULL);
  channel.reset(NULL);
  setStopped();
}
void WebConferenceDialog::disconnectConference() {
  play_list.close();
  setInOut(NULL,NULL);
  channel.reset(NULL);
  setStopped();
  time(&disconnect_ts);
}
Beispiel #5
0
void AnswerMachineDialog::onBye(const AmSipRequest& req)
{
  dlg->reply(req,200,"OK");

  setInOut(NULL, NULL);
  saveMessage();
  setStopped();
}
Beispiel #6
0
void GWSession::onSessionStart(const AmSipReply& reply) {
        DBG("GWSession::onSessionStart(reply)\n");
	DBG("calling ((mISDNChannel*)m_otherleg)->accept();\n");
        int ret=((mISDNChannel*)m_OtherLeg)->accept();
        DBG("GWSession::onSessionStart Setting Audio\n");
	setInOut((AmAudio *)(m_OtherLeg),(AmAudio *)(m_OtherLeg)); 
        AmSession::onSessionStart(reply);

}
void PinAuthConferenceDialog::onSessionStart(const AmSipRequest& req)
{ 
  state = EnteringPin;

  prompts.addToPlaylist(ENTER_PIN,  (long)this, play_list);

  // set the playlist as input and output
  setInOut(&play_list,&play_list);
}
void ServiceLineCallerDialog::onSessionStart(const AmSipRequest& req)
{

  AmB2ABCallerSession::onSessionStart(req);

  if(wav_file.open(filename,AmAudioFile::Read))
    throw string("AnnouncementDialog::onSessionStart: Cannot open file\n");
  
  setInOut(&playlist, &playlist);
  playlist.addToPlaylist(new AmPlaylistItem(&wav_file, NULL));
}
Beispiel #9
0
void MyCCDialog::onSessionStart(const AmSipRequest& req)
{
    DBG("MyCCDialog::onSessionStart");
    
    AmB2BCallerSession::onSessionStart(req);

    setInOut(&playlist, &playlist);
    addToPlaylist(MyCCFactory::InitialAnnouncement);

    setDtmfDetectionEnabled(true);
}
void DtmfTesterDialog::startSession(){
 
  if(wav_file.open(filename,AmAudioFile::Read))
    throw string("DtmfTesterDialog::onSessionStart: Cannot open file\n");

  string rec_fname = "/tmp/dtmftest_"+getLocalTag()+".wav";
  if(rec_file.open(rec_fname,AmAudioFile::Write))
    throw string("DtmfTesterDialog::onSessionStart: Cannot open rec_file\n");

  play_list.addToPlaylist(new AmPlaylistItem(&wav_file, NULL));
  setInOut(&rec_file, &play_list);
}
void WebConferenceDialog::onDtmf(int event, int duration)
{
  DBG("WebConferenceDialog::onDtmf: event %d duration %d\n", 
      event, duration);

  if (EnteringPin == state) {
    // not yet in conference
    if (event<10) {
      pin_str += int2str(event);
      DBG("added '%s': PIN is now '%s'.\n", 
	  int2str(event).c_str(), pin_str.c_str());
      play_list.close(false);
    } else if (event==10 || event==11) {
      // pound and star key
      // if required add checking of pin here...
      if (!pin_str.length()) {

	prompts.addToPlaylist(WRONG_PIN, (long)this, play_list, true);
      } else {
	state = EnteringConference;
	setInOut(NULL, NULL);
	play_list.close();
	for (size_t i=0;i<pin_str.length();i++) {
	  string num = "";
	  num[0] = pin_str[i];
	  DBG("adding '%s' to playlist.\n", num.c_str());

	  prompts.addToPlaylist(num,
				(long)this, play_list);
	}

       	setInOut(&play_list,&play_list);
	prompts.addToPlaylist(ENTERING_CONFERENCE,
			      (long)this, play_list);
	play_list.addToPlaylist(new AmPlaylistItem(&separator, NULL));
      }
    }
  }
}
Beispiel #12
0
void VoiceboxDialog::onSessionStart() { 
  if (pin.empty()) {
    state = Prompting;
    doMailboxStart();
  } else {
    state = EnteringPin;
    enqueueFront("pin_prompt");
  }

  // set the playlist as input and output
  setInOut(&play_list,&play_list);

  AmSession::onSessionStart();
}
void EarlyRecordDialog::onSessionStart(const AmSipReply& req)
{
  setInOut(NULL, NULL);

  a_msg.close();

  // replay the recorded early media
  msg_filename = "/tmp/" + getLocalTag() + ".wav";
  
  if(a_msg.open(msg_filename,AmAudioFile::Read,false))
    throw string("EarlyRecordDialog: couldn't open ") + 
      msg_filename + string(" for writing");

  setOutput(&a_msg);
}
void ConferenceDialog::setupAudio()
{
  if(!ConferenceFactory::JoinSound.empty()) {
	
    JoinSound.reset(new AmAudioFile());
    if(JoinSound->open(ConferenceFactory::JoinSound,
		       AmAudioFile::Read))
      JoinSound.reset(0);
  }

  if(!ConferenceFactory::DropSound.empty()) {
	
    DropSound.reset(new AmAudioFile());
    if(DropSound->open(ConferenceFactory::DropSound,
		       AmAudioFile::Read))
      DropSound.reset(0);
  }


  play_list.close();// !!!

  if(dialout_channel.get()){

    DBG("adding dialout_channel to the playlist (dialedout = %i)\n",dialedout);
    play_list.addToPlaylist(new AmPlaylistItem(dialout_channel.get(),
					       dialout_channel.get()));
  }
  else {

    channel.reset(AmConferenceStatus::getChannel(conf_id,getLocalTag()));

    play_list.addToPlaylist(new AmPlaylistItem(channel.get(),
					       channel.get()));
  }

  setInOut(&play_list,&play_list);
    
  setCallgroup(conf_id);
  
  MONITORING_LOG(getLocalTag().c_str(), "conf_id", conf_id.c_str());
	
  if(dialedout || !allow_dialout) {
    DBG("Dialout not enabled or dialout channel. Disabling DTMF detection.\n");
    setDtmfDetectionEnabled(false);
  }
}
Beispiel #15
0
void GWSession::onSessionStart(const AmSipRequest& req) {
        DBG("GWSession::onSessionStart\n");
        try {
            string sdp_reply;
            acceptAudio(req.body,req.hdrs,&sdp_reply);
            if(dlg.reply(req,200,"OK Isdn side state is: CONNECTED", "application/sdp",sdp_reply) != 0)
                     throw AmSession::Exception(500,"could not send response");
	}catch(const AmSession::Exception& e){
    	    ERROR("%i %s\n",e.code,e.reason.c_str());
            setStopped();
            dlg.reply(req,e.code,e.reason);
            return;
        }
        DBG("GWSession::onSessionStart Setting Audio\n");
	setInOut((AmAudio *)(m_OtherLeg),(AmAudio *)(m_OtherLeg));
	AmSession::onSessionStart(req);
	AmMediaProcessor::instance()->addSession(this, callgroup);
}	
Beispiel #16
0
bool CallTimerDialog::onOtherReply(const AmSipReply& reply)
{
  bool ret = false;

  if (m_state == BB_Dialing) {
    if (reply.code < 200) {
      DBG("Callee is trying... code %d\n", reply.code);
    }
    else if(reply.code < 300) {
      if(getCalleeStatus()  == Connected) {
        m_state = BB_Connected;
        setInOut(NULL, NULL);
	// startAccounting();
	// set the call timer
	AmArg di_args,ret;
	di_args.push(TIMERID_CALL_TIMER);
	di_args.push((int)call_time);  // in seconds
	di_args.push(dlg.local_tag.c_str());
        m_user_timer->invoke("setTimer", di_args, ret);
      }
    }
    else if(reply.code == 487 && dlg.getStatus() == AmSipDialog::Pending) {
      DBG("Stopping leg A on 487 from B with 487\n");
      dlg.reply(invite_req, 487, "Request terminated");
      setStopped();
      ret = true;
    }
    else if (reply.code >= 300 && dlg.getStatus() == AmSipDialog::Connected) {
      DBG("Callee final error in connected state with code %d\n",reply.code);
      terminateLeg();
    }
    else if (reply.code >= 300 && m_state == BB_Dialing) {
      DBG("Callee final error with code %d\n",reply.code);
      AmB2BCallerSession::onOtherReply(reply);
      // reset into non-b2b mode to get possible INVITE again
      sip_relay_only = false;
    } else {
      DBG("Callee final error with code %d\n",reply.code);
      AmB2BCallerSession::onOtherReply(reply);
    }
  }
  return ret;
}
void WebConferenceDialog::onSessionStart(const AmSipRequest& req) { 
  // direct room access?
  if (conf_id.empty()) {
    state = EnteringPin;    
    prompts.addToPlaylist(ENTER_PIN,  (long)this, play_list);
    // set the playlist as input and output
    setInOut(&play_list,&play_list);
  } else {
    DBG("########## direct connect conference #########\n"); 
    factory->newParticipant(conf_id, 
			    getLocalTag(), 
			    dlg.remote_party);
    factory->updateStatus(conf_id, 
			  getLocalTag(), 
			  ConferenceRoomParticipant::Connected,
			  "direct access: entered");
    state = InConference;
    connectConference(conf_id);
  }
}
bool SWPrepaidSIPDialog::onOtherReply(const AmSipReply& reply)
{
  bool ret = false;

  if (m_state == CC_Dialing) {
    if (reply.code < 200) {
      DBG("Callee is trying... code %d\n", reply.code);
    }
    else if(reply.code < 300) {
      if(getCalleeStatus()  == Connected) {
        m_state = CC_Connected;
        startAccounting();
        setInOut(NULL, NULL);

        // set the call timer
        AmArg di_args,ret;
        di_args.push(TIMERID_CREDIT_TIMEOUT);
        di_args.push(m_credit);  // in seconds
        di_args.push(dlg.local_tag.c_str());
        m_user_timer->invoke("setTimer", di_args, ret);
      }
    }
    else if(reply.code == 487 && dlg.getStatus() == AmSipDialog::Pending) {
      DBG("Canceling leg A on 487 from B");
      dlg.reply(m_localreq, 487, "Call terminated");
      setStopped();
      ret = true;
    }
    else if (reply.code >= 300 && dlg.getStatus() == AmSipDialog::Connected) {
      DBG("Callee final error in connected state with code %d\n",reply.code);
      terminateLeg();
    }
    else {
      DBG("Callee final error with code %d\n",reply.code);
      AmB2BCallerSession::onOtherReply(reply);
    }
  }
  return ret;
}
void Click2TransSession::onSessionStart(const AmSipRequest& req)
{
  if(dialog->isIncoming())
  {
    DBG("incoming session");

    try
    {
      std::string sdp_reply;
      acceptAudio(req.body,req.hdrs,&sdp_reply);
      if(dlg.reply(req,
	200,"OK INVITER IS CONNECTED", "application/sdp",
	  sdp_reply) != 0)
      {
	throw AmSession::Exception(500,"could not send response");
      }
    }
    catch(const AmSession::Exception& e)
    {
      ERROR("%i %s\n",e.code,e.reason.c_str());
      setStopped();
      dlg.reply(req,e.code,e.reason);
      return;
    }

    DBG("playing ringtone to inviter");

    setInOut(NULL,ringTone.get());
    AmSession::onSessionStart(req);
    AmMediaProcessor::instance()->addSession(this, callgroup);

    postEvent(new DialoutEvent(DoConnect));//TODO cleanup this allocation?
  }
  else if(dialog->isOutgoing())
  {
    DBG("outgoing session");
    //nothing to do
  }
}
void AnswerMachineDialog::onSessionStart(const AmSipRequest& req)
{
    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");

    msg_filename = "/tmp/" + getLocalTag() + "."
	+ AnswerMachineFactory::RecFileExt;
    
    if(a_msg.open(msg_filename,AmAudioFile::Write,true))
	throw string("AnswerMachine: couldn't open ") + 
	    msg_filename + string(" for writing");

    //a_msg.setRecordTime(AnswerMachineFactory::MaxRecordTime*1000);
    
    playlist.addToPlaylist(new AmPlaylistItem(&a_greeting,NULL));
    playlist.addToPlaylist(new AmPlaylistItem(&a_beep,NULL));
    //playlist.addToPlaylist(new AmPlaylistItem(NULL,&a_msg));

    setInOut(&playlist,&playlist);

    request2dict(req);
}
void AnswerMachineDialog::onSessionStart(const AmSipRequest& req)
{
  // disable DTMF detection - don't use DTMF here
  setDtmfDetectionEnabled(false);

#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;
    
  if(a_msg.open(msg_filename,AmAudioFile::Write,true))
    throw string("AnswerMachine: couldn't open ") + 
      msg_filename + string(" for writing");

  //a_msg.setRecordTime(AnswerMachineFactory::MaxRecordTime*1000);
    
  playlist.addToPlaylist(new AmPlaylistItem(&a_greeting,NULL));
  playlist.addToPlaylist(new AmPlaylistItem(&a_beep,NULL));
  //playlist.addToPlaylist(new AmPlaylistItem(NULL,&a_msg));

  setInOut(&playlist,&playlist);

  request2dict(req);
}
Beispiel #22
0
void EchoDialog::onSessionStart(const AmSipReply& req)
{
  rtp_str.setPlayoutType(playout_type);
  setInOut(&echo,&echo);
}
void PySemsDialog::onSessionStart(const AmSipRequest& req)
{
  DBG("PySemsDialog::onSessionStart\n");
  setInOut(&playlist,&playlist);
  AmSession::onSessionStart(req);
}
void SWPrepaidSIPDialog::onInvite(const AmSipRequest& req)
{
  // TODO: do reinvites get here? if so, don't set a timer then

  // TODO: errors thrown as exception don't seem to trigger a reply?

  // this will prevent us from being added to media processor
  setInOut(NULL,NULL);

  m_uuid = getHeader(req.hdrs,"P-Caller-Uuid");
  if(!m_uuid.length()) {
    ERROR("Application header P-Caller-Uuid not found\n");
    throw AmSession::Exception(500, "could not get UUID parameter");
  }

  m_proxy = getHeader(req.hdrs,"P-Proxy");
  if(!m_proxy.length()) {
    ERROR("Application header P-Proxy not found\n");
    throw AmSession::Exception(500, "could not get PROXY parameter");
  }

  m_ruri = getHeader(req.hdrs,"P-R-Uri");
  if(!m_ruri.length()) {
    ERROR("Application header P-R-Uri not found\n");
    throw AmSession::Exception(500, "could not get RURI parameter");
  }

  m_dest = getHeader(req.hdrs,"P-Acc-Dest");

  if(!m_dest.length()) {
    ERROR("Application header P-Acc-Dest not found\n");
    throw AmSession::Exception(500, "could not get destination pattern parameter");
  }

  DBG("UUID '%s' and pattern '%s' prepared for prepaid processing\n", m_uuid.c_str(), m_dest.c_str());

  m_starttime = time(NULL);
  m_localreq = req;

  AmArg di_args,ret;
  di_args.push(m_uuid.c_str());
  di_args.push((int)m_starttime);
  di_args.push(m_dest.c_str());
  m_cc_acc->invoke("getCredit", di_args, ret);
  m_credit = ret.get(0).asInt();

  if(m_credit == -1) {
    ERROR("Failed to fetch credit from accounting module\n");
    if(dlg.reply(req, 500, "Failed to fetch credit") != 0) {
      throw AmSession::Exception(500,"Failed to fetch credit");
    }
    return;
  }
  else if(m_credit == 0) {
    DBG("No credit left\n");
    m_state = CC_Teardown;
    if(dlg.reply(req, 402, "Unsufficient Credit") != 0) {
      throw AmSession::Exception(500,"Failed to reply 402");
    }
    setStopped();
    //throw AmSession::Exception(402, "Unsufficient Credit");
  }
  else {
    DBG("Credit for UUID %s is %d seconds, calling %s now\n", m_uuid.c_str(), m_credit, req.r_uri.c_str());
    m_state = CC_Dialing;

    if(dlg.reply(req, 101, "Connecting") != 0) {
      throw AmSession::Exception(500,"Failed to reply 101");
    }

    invite_req = req;
    dlg.updateStatus(req);
    recvd_req.insert(std::make_pair(req.cseq,req));

    connectCallee("<" + m_ruri + ">", m_proxy + ";sw_prepaid", true);
    set_sip_relay_only(true);
  }
}
Beispiel #25
0
void CallBackDialog::onSessionStart(const AmSipReply& rep) { 
  state = CBEnteringNumber;    
  prompts.addToPlaylist(WELCOME_PROMPT,  (long)this, play_list);
  // set the playlist as input and output
  setInOut(&play_list,&play_list);
}
void DSMCall::setInOutPlaylist() {
  DBG("setting playlist as input and output\n");
  setInOut(&playlist, &playlist);
}
void WebConferenceDialog::process(AmEvent* ev)
{
  // check conference events 
  ConferenceEvent* ce = dynamic_cast<ConferenceEvent*>(ev);
  if(ce && (conf_id == ce->conf_id)){
    switch(ce->event_id){

    case ConfNewParticipant: {
      DBG("########## new participant #########\n");
      if(ce->participants == 1){
	prompts.addToPlaylist(FIRST_PARTICIPANT, (long)this, play_list, true);
      } else {
	prompts.addToPlaylist(JOIN_SOUND, (long)this, play_list, true);
      }
    } break;
    
    case ConfParticipantLeft: {
      DBG("########## participant left ########\n");
      prompts.addToPlaylist(DROP_SOUND, (long)this, play_list, true);
    } break;

    default:
      break;
    }
    return;
  }

  // our item will fire this event
  AmPlaylistSeparatorEvent* sep_ev = dynamic_cast<AmPlaylistSeparatorEvent*>(ev);
  if (NULL != sep_ev) {
    // don't care for the id here
    if (EnteringConference == state) {
      state = InConference;
      DBG("########## connectConference after pin entry #########\n");
      connectConference(pin_str);
      factory->newParticipant(pin_str, 
			      getLocalTag(), 
			      dlg.remote_party);
      factory->updateStatus(pin_str, 
			    getLocalTag(), 
			    ConferenceRoomParticipant::Connected,
			    "entered");
    }    
  }
  // audio events
  AmAudioEvent* audio_ev = dynamic_cast<AmAudioEvent*>(ev);
  if (audio_ev  && 
      audio_ev->event_id == AmAudioEvent::noAudio) {
    DBG("########## noAudio event #########\n");
    return;
  }

  WebConferenceEvent* webconf_ev = dynamic_cast<WebConferenceEvent*>(ev);
  if (NULL != webconf_ev) {

    if (InConference != state) {

      if (webconf_ev->event_id == WebConferenceEvent::Kick) {
	DBG("########## WebConferenceEvent::Kick #########\n");
	dlg.bye(); 
	setInOut(NULL, NULL);
	setStopped();
	factory->updateStatus(conf_id, 
			      getLocalTag(), 
			      ConferenceRoomParticipant::Disconnecting,
			      "disconnect");
      }
    } else {
      
      switch(webconf_ev->event_id) {
      case WebConferenceEvent::Kick:  { 
	DBG("########## WebConferenceEvent::Kick #########\n");
	dlg.bye(); 
	disconnectConference();
	factory->updateStatus(conf_id, 
			      getLocalTag(), 
			      ConferenceRoomParticipant::Disconnecting,
			      "disconnect");
      } break;
      case WebConferenceEvent::Mute:  {  
	DBG("########## WebConferenceEvent::Mute #########\n"); 
	setInOut(NULL, &play_list);  
      } break;
      case WebConferenceEvent::Unmute: {  
	DBG("########## WebConferenceEvent::Unmute #########\n"); 
	setInOut(&play_list, &play_list);  
      } break;
      default: { WARN("ignoring unknown webconference event %d\n", webconf_ev->event_id); 
      } break;	
      }
    }
    return;
  }
  
  AmSession::process(ev);
}
void AnswerMachineDialog::onSessionStart(const AmSipRequest& req)
{
  // disable DTMF detection - don't use DTMF here
  setDtmfDetectionEnabled(false);

  // announcement mode - no receiving needed
  if (MODE_ANN == vm_mode)
    setReceiving(false);

#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 (announce_fp) {
    rewind(announce_fp);
    if (a_greeting.fpopen(DEFAULT_TYPE"."DEFAULT_AUDIO_EXT, 
			  AmAudioFile::Read, announce_fp) ||
	a_beep.open(beep_file,AmAudioFile::Read)) {
      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(beep_file,AmAudioFile::Read))
      throw string("AnswerMachine: could not open greeting or beep file\n");
  }
#else
  if (announce_fp) {
    if (a_greeting.fpopen(DEFAULT_TYPE"."DEFAULT_AUDIO_EXT, 
			  AmAudioFile::Read, announce_fp) ||
	a_beep.open(add2path(AnswerMachineFactory::AnnouncePath,1, "beep.wav"),
		    AmAudioFile::Read))
      throw string("AnswerMachine: could not open annoucement files\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;
    
  if (vm_mode != MODE_ANN) {
    if(a_msg.open(msg_filename,AmAudioFile::Write,true))
      throw string("AnswerMachine: couldn't open ") + 
	msg_filename + string(" for writing");
  }

  //a_msg.setRecordTime(AnswerMachineFactory::MaxRecordTime*1000);
    
  playlist.addToPlaylist(new AmPlaylistItem(&a_greeting,NULL));
  if (vm_mode != MODE_ANN) 
    playlist.addToPlaylist(new AmPlaylistItem(&a_beep,NULL));
  //playlist.addToPlaylist(new AmPlaylistItem(NULL,&a_msg));

  setInOut(&playlist,&playlist);

  char now[15];
  sprintf(now, "%d", (int) time(NULL));
  email_dict["ts"] = now;

}
void AnswerMachineDialog::onBye(const AmSipRequest& req)
{
  setInOut(NULL, NULL);
  saveMessage();
  setStopped();
}