diff --git a/apps/examples/Readme.examples b/apps/examples/Readme.examples new file mode 100644 index 00000000..e04464e0 --- /dev/null +++ b/apps/examples/Readme.examples @@ -0,0 +1,8 @@ + +This directory contains examples that illustrate how to +make use certain aspects of the SEMS framework rather than +be complete ready-to-use applications. The examples given +here can be a good start for further development, though. + +In each directory you will find a separate Readme file describing +the purpose of the example. \ No newline at end of file diff --git a/apps/examples/jukecall/Jukecall.cpp b/apps/examples/jukecall/Jukecall.cpp new file mode 100644 index 00000000..47ede127 --- /dev/null +++ b/apps/examples/jukecall/Jukecall.cpp @@ -0,0 +1,183 @@ +/* + * $Id: Announcement.cpp 145 2006-11-26 00:01:18Z sayer $ + * + * Copyright (C) 2006 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 "Jukecall.h" +#include "AmApi.h" +#include "AmUtils.h" +#include "sems.h" +#include "log.h" + +#define MOD_NAME "jukecall" + +EXPORT_SESSION_FACTORY(JukecallFactory,MOD_NAME); + +// you can replace this with configurable file +#define INITIAL_ANNOUNCEMENT "../apps/examples/jukecall/wav/greeting.wav" +#define JUKE_DIR "../apps/examples/jukecall/wav/" + +JukecallFactory::JukecallFactory(const string& _app_name) + : AmSessionFactory(_app_name) +{ +} + + +int JukecallFactory::onLoad() +{ + // read configuration + + DBG("JukecallFactory loaded.\n"); + return 0; +} + +AmSession* JukecallFactory::onInvite(const AmSipRequest& req) +{ + if (req.user.length() <= 3) { + throw AmSession::Exception(403, "Need a number to call"); + } + + JukecallSession* dlg = new JukecallSession(); + + return dlg; +} + +JukecallSession::JukecallSession() + : AmB2ABCallerSession() +{ +} + +JukecallSession::~JukecallSession() +{ +} + +void JukecallSession::onSessionStart(const AmSipRequest& req) +{ + DBG("-----------------------------------------------------------------\n"); + DBG("playing file\n"); + + if(initial_announcement.open(INITIAL_ANNOUNCEMENT,AmAudioFile::Read)) { + dlg.bye(); + throw string("CTConfDDialog::onSessionStart: Cannot open file '%s'\n", INITIAL_ANNOUNCEMENT); + } + + // set this as our output + setOutput(&initial_announcement); + + state = JC_initial_announcement; +} + +void JukecallSession::onDtmf(int event, int duration_msec) { + DBG("got DTMF %d\n", event); + + // no jukebox if other party is not connected + if (getCalleeStatus()!=AmB2ABCallerSession::Connected) + return; + + // no jukebox in the beginning and while playing + if (state != JC_connect) + return; + + DBG("playing back file...\n"); + + song.reset(new AmAudioFile()); + if (song->open(JUKE_DIR+int2str(event)+".wav",AmAudioFile::Read)) { + ERROR("could not open file\n"); + return; + } + setOutput(song.get()); + state = JC_juke; + + relayEvent(new JukeEvent(event)); +} + +void JukecallSession::process(AmEvent* event) +{ + + AmAudioEvent* audio_event = dynamic_cast(event); + if(audio_event && (audio_event->event_id == AmAudioEvent::cleared)){ + switch(state) { + case JC_initial_announcement: { + state = JC_connect; + string callee = "sip:" + dlg.user.substr(3) + "@" + dlg.domain; + DBG("-------------------------- connecting %s ------------------------\n", callee.c_str()); + connectCallee(callee, callee, + dlg.remote_party, dlg.remote_uri); + + return; + + } break; + + case JC_juke: { + DBG("reconnecting audio\n"); + reconnectAudio(); + state = JC_connect; + return; + }; break; + + default: { + DBG("cleared in other state.\n"); + return; + }; + } + + } + + AmB2ABCallerSession::process(event); +} + +AmB2ABCalleeSession* JukecallSession::createCalleeSession() { + AmB2ABCalleeSession* sess = new JukecalleeSession(getLocalTag()); + return sess; +} + +JukecalleeSession::JukecalleeSession(const string& other_tag) + : AmB2ABCalleeSession(other_tag) +{ + setDtmfDetectionEnabled(false); +} + + +void JukecalleeSession::process(AmEvent* event) { + JukeEvent* juke_event = dynamic_cast(event); + if(juke_event) { + song.reset(new AmAudioFile()); + if (song->open(JUKE_DIR+int2str(event->event_id)+".wav",AmAudioFile::Read)) { + ERROR("could not open file\n"); + return; + } + setOutput(song.get()); + return; + } + + AmAudioEvent* audio_event = dynamic_cast(event); + if(audio_event && (audio_event->event_id == AmAudioEvent::cleared)){ + DBG("reconnecting audio\n"); + reconnectAudio(); + return; + } + + AmB2ABCalleeSession::process(event); +} diff --git a/apps/examples/jukecall/Jukecall.h b/apps/examples/jukecall/Jukecall.h new file mode 100644 index 00000000..47a13911 --- /dev/null +++ b/apps/examples/jukecall/Jukecall.h @@ -0,0 +1,100 @@ +/* + * $Id: CTConfD.h 145 2006-11-26 00:01:18Z sayer $ + * + * Copyright (C) 2006 ipteo 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 + */ + +#ifndef _JUKECALL_H_ +#define _JUKECALL_H_ + +#include "AmB2ABSession.h" +#include "AmConfigReader.h" +#include "AmApi.h" + +#include +using std::string; + +class JukecallFactory: public AmSessionFactory +{ +public: + JukecallFactory(const string& _app_name); + + int onLoad(); + + AmSession* onInvite(const AmSipRequest& req); +}; + +class JukecallSession + : public AmB2ABCallerSession +{ + +public: + enum JukeLeg1_state { + JC_initial_announcement = 0, + JC_connect, + JC_juke + }; + +private: + // our state + JukeLeg1_state state; + AmAudioFile initial_announcement; + + auto_ptr song; + +protected: + AmB2ABCalleeSession* createCalleeSession(); + +public: + + JukecallSession(); + ~JukecallSession(); + + void onSessionStart(const AmSipRequest& req); + void process(AmEvent* event); + + void onDtmf(int event, int duration_msec); +}; + +class JukecalleeSession + : public AmB2ABCalleeSession { + + void process(AmEvent* event); + auto_ptr song; + +public: + JukecalleeSession(const string& other_tag); +}; + +class JukeEvent : public AmEvent { +public: + JukeEvent(int key) + : AmEvent(key) {} +}; + +#endif +// Local Variables: +// mode:C++ +// End: + diff --git a/apps/examples/jukecall/Makefile b/apps/examples/jukecall/Makefile new file mode 100644 index 00000000..39706128 --- /dev/null +++ b/apps/examples/jukecall/Makefile @@ -0,0 +1,14 @@ + +plug_in_name = jukecall + +module_ldflags = +module_cflags = + +module_extra_objs = +extra_install = jukecall_audio + +extra_clean = + +COREPATH ?=../../../core +include $(COREPATH)/plug-in/Makefile.app_module + diff --git a/apps/examples/jukecall/Readme.jukecall b/apps/examples/jukecall/Readme.jukecall new file mode 100644 index 00000000..fb71bc65 --- /dev/null +++ b/apps/examples/jukecall/Readme.jukecall @@ -0,0 +1,53 @@ +Jukecall + +This is an example of how to use the B2ABSession - a kind of +b2bua where SEMS stays in the media path, or media relay. + +Because SEMS stays in the path, its possible to react e.g. +on DTMF while in the call - and the jukecall example does +just this: +First it plays a welcome message to the caller, then it +connects to the originally dialled number stripped by the +first three digits. When the two parties are connected, +the first one can play some files into the call by pressing +the keys on the phone. + +for example: + +123@example.org SEMS jukecall 456@example.org + +| INVITE sip:500456 | | ++---------------------->| | +| 200 OK | | +|<----------------------| | +| | | +| play greeting.wav | | +|<======================| | +| | | +| | | +| | INVITE sip:456 | +| +---------------------->| +| | 200 OK | +| |<----------------------| +| | | +| | | +| connected through relay | +|<=====================>|<=====================>| +| | | +| DTMF 1 | | +|-=-=-=-=-=-=-=-=-=-=-=>| | +| | | +| play 1.wav | play 1.wav | +|<======================|======================>| +| | | +| connected through relay | +|<=====================>|<=====================>| +| | | +| DTMF 3 | | +|-=-=-=-=-=-=-=-=-=-=-=>| | +| | | +| play 3.wav | play 3.wav | +|<======================|======================>| +| | | + +aso. diff --git a/apps/examples/jukecall/wav/1.wav b/apps/examples/jukecall/wav/1.wav new file mode 100644 index 00000000..62f54054 Binary files /dev/null and b/apps/examples/jukecall/wav/1.wav differ diff --git a/apps/examples/jukecall/wav/2.wav b/apps/examples/jukecall/wav/2.wav new file mode 100644 index 00000000..df90a0b5 Binary files /dev/null and b/apps/examples/jukecall/wav/2.wav differ diff --git a/apps/examples/jukecall/wav/3.wav b/apps/examples/jukecall/wav/3.wav new file mode 100644 index 00000000..a9ee6681 Binary files /dev/null and b/apps/examples/jukecall/wav/3.wav differ diff --git a/apps/examples/jukecall/wav/4.wav b/apps/examples/jukecall/wav/4.wav new file mode 100644 index 00000000..b22cae9f Binary files /dev/null and b/apps/examples/jukecall/wav/4.wav differ diff --git a/apps/examples/jukecall/wav/greeting.wav b/apps/examples/jukecall/wav/greeting.wav new file mode 100644 index 00000000..5ee95746 Binary files /dev/null and b/apps/examples/jukecall/wav/greeting.wav differ