From baa0684af777393d11fd9beafccaccbd49c71661 Mon Sep 17 00:00:00 2001 From: Stefan Sayer Date: Thu, 7 Jun 2007 18:36:19 +0000 Subject: [PATCH] conference example: room number entry via DTMF git-svn-id: http://svn.berlios.de/svnroot/repos/sems/trunk@354 8eb893ce-cfd4-0310-b710-fb5ebe64c474 --- apps/examples/pinauthconference/Makefile | 9 + .../pinauthconference/PinAuthConference.cpp | 242 ++++++++++++++++++ .../pinauthconference/PinAuthConference.h | 110 ++++++++ .../etc/.pinauthconference.conf.swp | Bin 0 -> 4096 bytes .../etc/pinauthconference.conf | 12 + apps/examples/pinauthconference/wav/beep.wav | Bin 0 -> 1646 bytes 6 files changed, 373 insertions(+) create mode 100644 apps/examples/pinauthconference/Makefile create mode 100644 apps/examples/pinauthconference/PinAuthConference.cpp create mode 100644 apps/examples/pinauthconference/PinAuthConference.h create mode 100644 apps/examples/pinauthconference/etc/.pinauthconference.conf.swp create mode 100644 apps/examples/pinauthconference/etc/pinauthconference.conf create mode 100644 apps/examples/pinauthconference/wav/beep.wav diff --git a/apps/examples/pinauthconference/Makefile b/apps/examples/pinauthconference/Makefile new file mode 100644 index 00000000..7be35dd4 --- /dev/null +++ b/apps/examples/pinauthconference/Makefile @@ -0,0 +1,9 @@ +plug_in_name = pinauthconference + +module_ldflags = +module_cflags = + +extra_install = $(plug_in_name)_audio + +COREPATH ?=../../../core +include $(COREPATH)/plug-in/Makefile.app_module diff --git a/apps/examples/pinauthconference/PinAuthConference.cpp b/apps/examples/pinauthconference/PinAuthConference.cpp new file mode 100644 index 00000000..8d60ae8b --- /dev/null +++ b/apps/examples/pinauthconference/PinAuthConference.cpp @@ -0,0 +1,242 @@ +/* + * $Id: PinAuthConference.cpp 288 2007-03-28 16:32:02Z sayer $ + * + * Copyright (C) 2007 iptego GmbH + * + * 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: + * info@iptel.org + * + * 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 "PinAuthConference.h" +#include "AmConferenceStatus.h" +#include "AmUtils.h" +#include "log.h" + +#define APP_NAME "pinauthconference" + +EXPORT_SESSION_FACTORY(PinAuthConferenceFactory,APP_NAME); + +PinAuthConferenceFactory::PinAuthConferenceFactory(const string& _app_name) + : AmSessionFactory(_app_name) +{ +} + +string PinAuthConferenceFactory::DigitsDir; +PlayoutType PinAuthConferenceFactory::m_PlayoutType = ADAPTIVE_PLAYOUT; + +int PinAuthConferenceFactory::onLoad() +{ + AmConfigReader cfg; + if(cfg.loadFile(AmConfig::ModConfigPath + string(APP_NAME)+ ".conf")) + return -1; + + // get application specific global parameters + configureModule(cfg); + + // get prompts + AM_PROMPT_START; + AM_PROMPT_ADD(FIRST_PARTICIPANT, ANNOUNCE_PATH "first_paricipant.wav"); + AM_PROMPT_ADD(JOIN_SOUND, ANNOUNCE_PATH "beep.wav"); + AM_PROMPT_ADD(DROP_SOUND, ANNOUNCE_PATH "beep.wav"); + AM_PROMPT_ADD(ENTER_PIN, ANNOUNCE_PATH "enter_pin.wav"); + AM_PROMPT_ADD(WRONG_PIN, ANNOUNCE_PATH "wrong_pin.wav"); + AM_PROMPT_ADD(ENTERING_CONFERENCE, ANNOUNCE_PATH "entering_conference.wav"); + AM_PROMPT_END(prompts, cfg, APP_NAME); + + DigitsDir = cfg.getParameter("digits_dir"); + if (DigitsDir.length() && DigitsDir[DigitsDir.length()-1]!='/') + DigitsDir+='/'; + + if (!DigitsDir.length()) { + WARN("No digits_dir specified in configuration.\n"); + } + for (int i=0;i<10;i++) + prompts.setPrompt(int2str(i), DigitsDir+int2str(i)+".wav", APP_NAME); + + string playout_type = cfg.getParameter("playout_type"); + if (playout_type == "simple") { + m_PlayoutType = SIMPLE_PLAYOUT; + DBG("Using simple (fifo) buffer as playout technique.\n"); + } else if (playout_type == "adaptive_jb") { + m_PlayoutType = JB_PLAYOUT; + DBG("Using adaptive jitter buffer as playout technique.\n"); + } else { + DBG("Using adaptive playout buffer as playout technique.\n"); + } + + return 0; +} + +// incoming calls - req is INVITE +AmSession* PinAuthConferenceFactory::onInvite(const AmSipRequest& req) +{ + return new PinAuthConferenceDialog(prompts); +} + +// outgoing calls - rep is 200 class response to INVITE +AmSession* PinAuthConferenceFactory::onInvite(const AmSipReply& rep) +{ + return new PinAuthConferenceDialog(prompts); +} + +PinAuthConferenceDialog::PinAuthConferenceDialog(AmPromptCollection& prompts) + : play_list(this), separator(this, 0), prompts(prompts), state(None) +{ + // set configured playout type + rtp_str.setPlayoutType(PinAuthConferenceFactory::m_PlayoutType); +} + +PinAuthConferenceDialog::~PinAuthConferenceDialog() +{ + prompts.cleanup((long)this); +} + +void PinAuthConferenceDialog::connectConference(const string& room) { + // set the conference id ('conference room') + conf_id = room; + + // disconnect in/out for safety + setInOut(NULL, NULL); + + // we need to be in the same callgroup as the other + // people in the conference (important if we have multiple + // MediaProcessor threads + changeCallgroup(conf_id); + + // get a channel from the status + channel.reset(AmConferenceStatus::getChannel(conf_id,getLocalTag())); + + // clear the playlist + play_list.close(); + + // add the channel to our playlist + play_list.addToPlaylist(new AmPlaylistItem(channel.get(), + channel.get())); + + // set the playlist as input and output + setInOut(&play_list,&play_list); +} + +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 PinAuthConferenceDialog::onBye(const AmSipRequest& req) +{ + play_list.close(); + setInOut(NULL,NULL); + channel.reset(NULL); + setStopped(); +} + +void PinAuthConferenceDialog::process(AmEvent* ev) +{ + // check conference events + ConferenceEvent* ce = dynamic_cast(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(ev); + if (NULL != sep_ev) { + // don't care for the id here + if (EnteringConference == state) { + state = InConference; + connectConference(pin_str); + DBG("connectConference. **********************\n"); + } + } + // audio events + AmAudioEvent* audio_ev = dynamic_cast(ev); + if (audio_ev && + audio_ev->event_id == AmAudioEvent::noAudio) { + DBG("received noAudio event. **********************\n"); + return; + } + + AmSession::process(ev); +} + +void PinAuthConferenceDialog::onDtmf(int event, int duration) +{ + DBG("PinAuthConferenceDialog::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()); + } 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 +#include +using std::map; +using std::string; + +class ConferenceStatus; +class ConferenceStatusContainer; + +// configuration parameter names +#define ENTERING_CONFERENCE "entering_conference" +#define FIRST_PARTICIPANT "first_participant" +#define JOIN_SOUND "join_sound" +#define DROP_SOUND "drop_sound" +#define ENTER_PIN "enter_pin" +#define WRONG_PIN "wrong_pin" +#define ENTERING_CONFERENCE "entering_conference" + +// default path for files +#define ANNOUNCE_PATH "../apps/examples/pinauthconference/wav/" + +class PinAuthConferenceFactory : public AmSessionFactory +{ + + AmPromptCollection prompts; +public: + static string DigitsDir; + static PlayoutType m_PlayoutType; + + PinAuthConferenceFactory(const string& _app_name); + AmSession* onInvite(const AmSipRequest&); + AmSession* onInvite(const AmSipReply&); + int onLoad(); +}; + +class PinAuthConferenceDialog : public AmSession +{ +public: + enum PinAuthConferenceState { + None, + EnteringPin, + EnteringConference, + InConference + }; + +private: + AmPlaylist play_list; + AmPlaylistSeparator separator; + + AmPromptCollection& prompts; + + // our connection to the conference + auto_ptr channel; + string conf_id; + string pin_str; + + void connectConference(const string& room); + + PinAuthConferenceState state; + +public: + PinAuthConferenceDialog(AmPromptCollection& prompts); + ~PinAuthConferenceDialog(); + + void process(AmEvent* ev); + void onSessionStart(const AmSipRequest& req); + void onDtmf(int event, int duration); + void onBye(const AmSipRequest& req); +}; + +#endif +// Local Variables: +// mode:C++ +// End: + diff --git a/apps/examples/pinauthconference/etc/.pinauthconference.conf.swp b/apps/examples/pinauthconference/etc/.pinauthconference.conf.swp new file mode 100644 index 0000000000000000000000000000000000000000..55c8a6e30c334386c61da6cb6dd1e937f35bb49f GIT binary patch literal 4096 zcmeIuF$%&!5Czb=fFRmhMC~(C3vUpxuo1M?b(xTmWOv!wC0@omctj1BLa@*La{h;b zch4?|W3o>(_+$$3%*))K7Vx?OaG*k&z8FrY*bOhfEk^d(SgjgluaT+cYiE6p!ADc0 za*mN6s&x%9y2_{+N^MO+o{T1>pntDvKltalY(!x60u$J6H`#i%Oy;xm=rsgD1Vlgt QL_h>YKmo&y!@4r$%3yY8a*i|PC|XI9-KK>K1gwN?$!em>c=!FkrLMJ9Cxv@pG7==ADycs-Rc(r=^}>ZhZl+pm_< z9gOevMHx2_y@g0uQ+3HJ3*;VZW`1ojkN7Up>K&ciu%BXND{a_=)lT)Qx=tOEM5(vQ zqUd3*eYHHJLx_AZ+-cux_zh$`ddg3>vypbV+hN1#EN=2^*i(ECBn~e)jv0r7(k5T} zTU!s(jE7hvCPOf36Dr-;_6shVs=07X0`W)7_Tu>#Q?O0sTnx;1kkV#S=-ccImf5Il zl^G#R%{m2RJP)*+hr53=pNDXhLcVg7C@z^#x)&d@CJdfiUUj24JS;>!6D&4h%^Q4v zq=6%dqyFNxg}N-*)!>=SYiI|k!^ej#wGhRX%-P`P;fj@z&xEB9*16F+a`iK4w-)x( zwAMjPop5$^9Us!xeZIN0To`gfo-jDcxJkQnVwtuIU(WWdh1ysU`Un3cdN#^xRUf~q zrDBb~c&dkyg4i0FM|*3+ahvhqQ~xqX!L8}|?NPN1{Elu0UO8$&s4vwsd#n2dPnl*x z&bFrrr%Ej&vT9HuY9oAxVWWiWl|tzkDwB!7U1o5!tu&S@ywj~J`Ea(2KPzh=0J-u# z_eCqVl1ui9A*%Lq*k8`SH&FHwyBx{+2M%mpE%Um^Da%Hd<5-wHD+Vj2XYMlD%`jqp z3JYSj!IqtzDp9g3aB#}}A=Zfn=Mu9!Q6<|U;UpQJ;4%i!VyD|(MN;57Plq3Lu_S#( zmbZKh2LxR%QxVr)39&AcyG1M96lAzKUu3x-AnW;aN$CY)#LIm$@}8Rw#0$128Rv@= z$75~Lzq?Cd`Nio(n|vVALor6fYIiR_F2KT1U)(%RXuK?GaMK(R{LpIqoS!Gar~eWFeiAFWh7XKJwEQ~kNzg@!JyP){FEp+aETsFb(fC_)k}xE?z#g0akt%MWTQ#-@3# z`=~h+QcVQ~6U~0`HzRIdW-;(@_AQ)hslqc8fiuNa4F0XMrFYuSBh~mhtJU~lShZ!A zzUCJ}`S32sbBD9Qmh!Q7edtnhZJtr;FyBe9I@fs_5e7|6 zc>^G%OZ6rD)uiB}e%qJdgyKV2PR)hxr-;?dq?PIZPeAY4_N#$?NA86k>l-nlZ~Kn#*XxBM&ZstT9f#|_ej>% zFt5}sLEPJ_7XI5`p{n6*8mmzcxuKP|&x02+rM}%*^56qp8Dh8pH2jYsP;G~it=b|Q zhWB-3{P8QARK^UJRK}n@lG7sf6Dw7gLTPNMN6qFc+R&>T$m4m!(LH~F@fmn~WcRW61fhA6H@m)c5@*C2(t6_8aC}K|Zs*EvjP5p(-2K%JtSqa{ NyDnD}v0XvJ{|EeJZ@~Zn literal 0 HcmV?d00001