1 /* 2 * Copyright (C) 2006 iptego GmbH 3 * 4 * This file is part of SEMS, a free SIP media server. 5 * 6 * SEMS is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * For a license to use the sems software under conditions 12 * other than those described here, or to purchase support for this 13 * software, please contact iptel.org by e-mail at the following addresses: 14 * info@iptel.org 15 * 16 * SEMS is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with this program; if not, write to the Free Software 23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 */ 25 26 #include "Jukecall.h" 27 #include "AmApi.h" 28 #include "AmUtils.h" 29 #include "sems.h" 30 #include "log.h" 31 32 #define MOD_NAME "jukecall" 33 34 EXPORT_SESSION_FACTORY(JukecallFactory,MOD_NAME); 35 36 // you can replace this with configurable file 37 #define INITIAL_ANNOUNCEMENT "../apps/examples/jukecall/wav/greeting.wav" 38 #define JUKE_DIR "../apps/examples/jukecall/wav/" 39 40 JukecallFactory::JukecallFactory(const string& _app_name) 41 : AmSessionFactory(_app_name) 42 { 43 } 44 45 46 int JukecallFactory::onLoad() 47 { 48 // read configuration 49 50 DBG("JukecallFactory loaded.\n"); 51 return 0; 52 } 53 54 AmSession* JukecallFactory::onInvite(const AmSipRequest& req, const string& app_name, 55 const map<string,string>& app_params) 56 { 57 if (req.user.length() <= 3) { 58 throw AmSession::Exception(403, "Need a number to call"); 59 } 60 61 JukecallSession* dlg = new JukecallSession(); 62 63 return dlg; 64 } 65 66 JukecallSession::JukecallSession() 67 : AmB2ABCallerSession(), state(JC_none) 68 { 69 } 70 71 JukecallSession::~JukecallSession() 72 { 73 } 74 75 void JukecallSession::onSessionStart() 76 { 77 if (state != JC_none) { 78 // reinvite 79 AmB2ABCallerSession::onSessionStart(); 80 return; 81 } 82 83 DBG("-----------------------------------------------------------------\n"); 84 DBG("playing file\n"); 85 86 if(initial_announcement.open(INITIAL_ANNOUNCEMENT,AmAudioFile::Read)) { 87 dlg->bye(); 88 throw string("CTConfDDialog::onSessionStart: Cannot open file '%s'\n", INITIAL_ANNOUNCEMENT); 89 } 90 91 // set this as our output 92 setOutput(&initial_announcement); 93 94 state = JC_initial_announcement; 95 96 AmB2ABCallerSession::onSessionStart(); 97 } 98 99 void JukecallSession::onDtmf(int event, int duration_msec) { 100 DBG("got DTMF %d\n", event); 101 102 // no jukebox if other party is not connected 103 if (getCalleeStatus()!=AmB2ABCallerSession::Connected) 104 return; 105 106 // no jukebox in the beginning and while playing 107 if (state != JC_connect) 108 return; 109 110 DBG("playing back file...\n"); 111 112 song.reset(new AmAudioFile()); 113 if (song->open(JUKE_DIR+int2str(event)+".wav",AmAudioFile::Read)) { 114 ERROR("could not open file\n"); 115 return; 116 } 117 setOutput(song.get()); 118 state = JC_juke; 119 120 relayEvent(new JukeEvent(event)); 121 } 122 123 void JukecallSession::process(AmEvent* event) 124 { 125 126 AmAudioEvent* audio_event = dynamic_cast<AmAudioEvent*>(event); 127 if(audio_event && (audio_event->event_id == AmAudioEvent::cleared)){ 128 switch(state) { 129 case JC_initial_announcement: { 130 state = JC_connect; 131 string callee = "sip:" + dlg->getUser().substr(3) + "@" + dlg->getDomain(); 132 DBG("-------------------------- connecting %s ------------------------\n", callee.c_str()); 133 connectCallee(callee, callee, 134 dlg->getRemoteParty(), dlg->getRemoteUri()); 135 136 return; 137 138 } break; 139 140 case JC_juke: { 141 DBG("reconnecting audio\n"); 142 connectSession(); 143 state = JC_connect; 144 return; 145 }; break; 146 147 default: { 148 DBG("cleared in other state.\n"); 149 return; 150 }; 151 } 152 153 } 154 155 AmB2ABCallerSession::process(event); 156 } 157 158 AmB2ABCalleeSession* JukecallSession::createCalleeSession() { 159 AmB2ABCalleeSession* sess = new JukecalleeSession(getLocalTag(), connector); 160 return sess; 161 } 162 163 JukecalleeSession::JukecalleeSession(const string& other_tag, 164 AmSessionAudioConnector* connector) 165 : AmB2ABCalleeSession(other_tag, connector) 166 { 167 setDtmfDetectionEnabled(false); 168 } 169 170 171 void JukecalleeSession::process(AmEvent* event) { 172 JukeEvent* juke_event = dynamic_cast<JukeEvent*>(event); 173 if(juke_event) { 174 song.reset(new AmAudioFile()); 175 if (song->open(JUKE_DIR+int2str(event->event_id)+".wav",AmAudioFile::Read)) { 176 ERROR("could not open file\n"); 177 return; 178 } 179 setOutput(song.get()); 180 return; 181 } 182 183 AmAudioEvent* audio_event = dynamic_cast<AmAudioEvent*>(event); 184 if(audio_event && (audio_event->event_id == AmAudioEvent::cleared)){ 185 DBG("reconnecting audio\n"); 186 connectSession(); 187 return; 188 } 189 190 AmB2ABCalleeSession::process(event); 191 } 192