Logo
  • Main Page
  • Related Pages
  • Modules
  • Classes
  • Files

mmssip.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2005-2007 Stefan Schwarzer, Jens Schneider,             *
00003  *                           Matthias Hardt, Guido Madaus                  *
00004  *                                                                         *
00005  *   Copyright (C) 2007-2008 BerLinux Solutions GbR                        *
00006  *                           Stefan Schwarzer & Guido Madaus               *
00007  *                                                                         *
00008  *   Copyright (C) 2009-2013 BerLinux Solutions GmbH                       *
00009  *                                                                         *
00010  *   Authors:                                                              *
00011  *      Stefan Schwarzer   <stefan.schwarzer@diskohq.org>,                 *
00012  *      Matthias Hardt     <matthias.hardt@diskohq.org>,                   *
00013  *      Jens Schneider     <jens.schneider@diskohq.org>,                   *
00014  *      Guido Madaus       <guido.madaus@diskohq.org>,                     *
00015  *      Patrick Helterhoff <patrick.helterhoff@diskohq.org>,               *
00016  *      René Bählkow       <rene.baehlkow@diskohq.org>                     *
00017  *                                                                         *
00018  *   This library is free software; you can redistribute it and/or         *
00019  *   modify it under the terms of the GNU Lesser General Public            *
00020  *   License version 2.1 as published by the Free Software Foundation.     *
00021  *                                                                         *
00022  *   This library is distributed in the hope that it will be useful,       *
00023  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00024  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00025  *   Lesser General Public License for more details.                       *
00026  *                                                                         *
00027  *   You should have received a copy of the GNU Lesser General Public      *
00028  *   License along with this library; if not, write to the                 *
00029  *   Free Software Foundation, Inc.,                                       *
00030  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
00031  **************************************************************************/
00032 
00033 #ifdef __HAVE_MMSSIP__
00034 
00035 #ifdef PJSIP_AUTH_AUTO_SEND_NEXT
00036 #undef PJSIP_AUTH_AUTO_SEND_NEXT
00037 #endif
00038 #define PJSIP_AUTH_AUTO_SEND_NEXT 1
00039 
00040 #ifdef PJSIP_AUTH_HEADER_CACHING
00041 #undef PJSIP_AUTH_HEADER_CACHING
00042 #endif
00043 #define PJSIP_AUTH_HEADER_CACHING 1
00044 
00045 
00046 #include "mmstools/tools.h"
00047 #include "mmstools/mmserror.h"
00048 #include "mmssip/mmssip.h"
00049 
00050 static MMSSip           *thiz = NULL;
00051 static bool             registered = false;
00052 static pjsua_player_id  ringtonePlayer = PJSUA_INVALID_ID;
00053 static pjsua_player_id  busytonePlayer = PJSUA_INVALID_ID;
00054 static pjsua_player_id  callingtonePlayer = PJSUA_INVALID_ID;
00055 
00056 static void onIncomingCall(pjsua_acc_id, pjsua_call_id, pjsip_rx_data*);
00057 static void onCallState(pjsua_call_id, pjsip_event*);
00058 static void onCallMediaState(pjsua_call_id);
00059 static void onRegistrationState(pjsua_acc_id);
00060 static void onBuddyState(pjsua_buddy_id);
00061 
00062 static void logCallback(int level, const char *data, int len) {
00063     DEBUGMSG("MMSSIP", data);
00064 }
00065 
00066 MMSSip::MMSSip(const string    &user,
00067                const string    &passwd,
00068                const string    &registrar,
00069                const string    &realm,
00070                const string    &stunserver,
00071                const string    &nameserver,
00072                const short int &localPort) :
00073     stunserver(stunserver),
00074     nameserver(nameserver),
00075     localPort(localPort),
00076     defaultAccount(-1) {
00077 
00078     /* only one instance of mmssip allowed */
00079     if(thiz) {
00080         DEBUGMSG("MMSSIP", "There's already an instance of MMSSIP running.");
00081         throw MMSError(0, "There's already an instance of MMSSIP running.");
00082     }
00083 
00084     thiz = this;
00085 
00086     pj_status_t status;
00087 
00088     /* create pjsua */
00089     status = pjsua_create();
00090     if(status != PJ_SUCCESS) {
00091         DEBUGMSG("MMSSIP", "Error initializing SIP stack (pjsua_create)");
00092         throw MMSError(0, "Error initializing SIP stack (pjsua_create)");
00093     }
00094     DEBUGMSG("MMSSIP", "SIP stack init #1");
00095 
00096     /* configure pjsua */
00097     pjsua_config         cfg;
00098     pjsua_logging_config logCfg;
00099 
00100     pjsua_config_default(&cfg);
00101     cfg.user_agent             = pj_str((char*)"Disko SIP stack");
00102     if(stunserver != "") {
00103         DEBUGMSG("MMSSIP", "Using STUN server " + stunserver);
00104         cfg.stun_host          = pj_str((char*)stunserver.c_str());
00105     }
00106     if(nameserver != "") {
00107         DEBUGMSG("MMSSIP", "Using nameserver " + nameserver);
00108         cfg.nameserver[0]      = pj_str((char*)nameserver.c_str());
00109     }
00110     cfg.cb.on_incoming_call    = &onIncomingCall;
00111     cfg.cb.on_call_media_state = &onCallMediaState;
00112     cfg.cb.on_call_state       = &onCallState;
00113     cfg.cb.on_reg_state        = &onRegistrationState;
00114     cfg.cb.on_buddy_state      = &onBuddyState;
00115 
00116     pjsua_logging_config_default(&logCfg);
00117     logCfg.level = 1;
00118 #ifdef __ENABLE_LOG__
00119     logCfg.console_level = 4;
00120     logCfg.cb = logCallback;
00121 #else
00122     logCfg.console_level = 0;
00123 #endif
00124 
00125     status = pjsua_init(&cfg, &logCfg, NULL);
00126     if(status != PJ_SUCCESS) {
00127         DEBUGMSG("MMSSIP", "Error initializing SIP stack (pjsua_init)");
00128         throw MMSError(0, "Error initializing SIP stack (pjsua_init)");
00129     }
00130 
00131     DEBUGMSG("MMSSIP", "SIP stack init #2");
00132 
00133     /* add UDP transport */
00134     pjsua_transport_config transCfg;
00135 
00136     pjsua_transport_config_default(&transCfg);
00137     transCfg.port = localPort;
00138     status = pjsua_transport_create(PJSIP_TRANSPORT_UDP, &transCfg, NULL);
00139     if(status != PJ_SUCCESS) {
00140         DEBUGMSG("MMSSIP", "Error initializing SIP stack (pjsua_transport_create)");
00141         throw MMSError(0, "Error initializing SIP stack (pjsua_transport_create)");
00142     }
00143 
00144     DEBUGMSG("MMSSIP", "UDP transport created");
00145 
00146     /* start pjsua */
00147     status = pjsua_start();
00148     if(status != PJ_SUCCESS) {
00149         DEBUGMSG("MMSSIP", "Error starting SIP stack (pjsua_start)");
00150         throw MMSError(0, "Error starting SIP stack (pjsua_start)");
00151     }
00152 
00153     DEBUGMSG("MMSSIP", "SIP stack started");
00154 
00155     if(user != "") {
00156         if(!this->registerAccount(user, passwd, registrar, realm, true)) {
00157             DEBUGMSG("MMSSIP", "Error registering account");
00158             throw MMSError(0, "Error registering account");
00159         }
00160     }
00161 
00162     this->onCallSuccessfull    = new sigc::signal<void, int, int>;
00163     this->onCallIncoming       = new sigc::signal<void, int, string, int>;
00164     this->onCallDisconnected   = new sigc::signal<void, int, int>;
00165     this->onCalling            = new sigc::signal<void, int, int>;
00166     this->onBuddyStatus        = new sigc::signal<void, MMSSipBuddy>;
00167 }
00168 
00169 MMSSip::~MMSSip() {
00170     if(!pj_thread_is_registered()) {
00171         MMSSipThread tInfo;
00172         pj_bzero(tInfo.desc, sizeof(pj_thread_desc));
00173         if(pj_thread_register("MMSSIP", tInfo.desc, &tInfo.thread) == PJ_SUCCESS)
00174             pjsua_destroy();
00175     }
00176 
00177     if(this->onCallSuccessfull) {
00178         this->onCallSuccessfull->clear();
00179         delete this->onCallSuccessfull;
00180     }
00181     if(this->onCallIncoming) {
00182         this->onCallIncoming->clear();
00183         delete this->onCallIncoming;
00184     }
00185     if(this->onCallDisconnected) {
00186         this->onCallDisconnected->clear();
00187         delete this->onCallDisconnected;
00188     }
00189     if(this->onCalling) {
00190         this->onCalling->clear();
00191         delete this->onCalling;
00192     }
00193     if(this->onBuddyStatus) {
00194         this->onBuddyStatus->clear();
00195         delete this->onBuddyStatus;
00196     }
00197     this->accounts.clear();
00198     this->buddies.clear();
00199 }
00200 
00201 /**
00202  * Register an account.
00203  *
00204  * @param   user        [in]    user name
00205  * @param   passwd      [in]    password
00206  * @param   registrar   [in]    registrar
00207  * @param   realm       [in]    realm
00208  * @param   defaultAcc  [in]    use this as default account for incoming/outgoing calls
00209  * @param   autoanswer  [in]    automatically answer incoming calls
00210  *
00211  * @note If you're using the autoanswer feature, all other active calls
00212  * will be disconnected, when an incoming call arrives.
00213  *
00214  * @return  true, if account was registered successfully
00215  */
00216 const bool MMSSip::registerAccount(const string &user,
00217                                    const string &passwd,
00218                                    const string &registrar,
00219                                    const string &realm,
00220                                    const bool defaultAcc,
00221                                    const bool autoanswer) {
00222     pj_status_t         status;
00223     pjsua_acc_config    accCfg;
00224     pjsua_acc_id        accID;
00225     char                tmpid[256], tmpreg[256];
00226 
00227     DEBUGMSG("MMSSIP", "Registering account " + user + "@" + registrar +
00228             "(default: " + (defaultAcc ? "true" : "false") +
00229              ", autoanswer: " + (autoanswer ? "true" : "false") + ")");
00230 
00231     snprintf(tmpid, sizeof(tmpid), "sip:%s@%s", user.c_str(), registrar.c_str());
00232     snprintf(tmpreg, sizeof(tmpreg), "sip:%s", realm.c_str());
00233 
00234     pjsua_acc_config_default(&accCfg);
00235     accCfg.reg_timeout  = 60;
00236     accCfg.id         = pj_str(tmpid);
00237     accCfg.reg_uri    = pj_str(tmpreg);
00238     if(defaultAcc) accCfg.priority += 1;
00239     accCfg.cred_count = 1;
00240     accCfg.cred_info[0].realm     = pj_str((char*)"*");
00241     accCfg.cred_info[0].scheme    = pj_str((char*)"Digest");
00242     accCfg.cred_info[0].username  = pj_str((char*)user.c_str());
00243     accCfg.cred_info[0].data_type = 0;
00244     accCfg.cred_info[0].data      = pj_str((char*)passwd.c_str());
00245     accCfg.publish_enabled        = PJ_FALSE;
00246 
00247     status = pjsua_acc_add(&accCfg, (defaultAcc ? PJ_TRUE : PJ_FALSE), &accID);
00248     if(status != PJ_SUCCESS) {
00249         DEBUGMSG("MMSSIP", "Error registering account sip:" + user + "@" + registrar + " (pjsua_acc_add)");
00250         return false;
00251     }
00252 
00253     DEBUGMSG("MMSSIP", "Account " + user + "@" + registrar + " has ID " + iToStr(accID));
00254 
00255     MMSSipAccount acc = {user, passwd, registrar, realm, autoanswer};
00256     this->accounts[accID] = acc;
00257     if(defaultAcc)
00258         this->defaultAccount = accID;
00259 
00260     return true;
00261 }
00262 
00263 /*
00264  * Calls a given user.
00265  *
00266  * @param   user    [in]    user id
00267  * @param   domain  [in]    domain for users sip account
00268  *
00269  * @note The SIP uri will be "sip:id@domain".
00270  *
00271  * @return call id
00272  *
00273  * @see MMSSip::hangup()
00274  */
00275 const int MMSSip::call(const string &user, const string &domain) {
00276     pj_status_t    status;
00277     pj_str_t       uri;
00278     pjsua_call_id  call;
00279     char           tmp[1024];
00280 
00281     if(!registered) {
00282         DEBUGMSG("MMSSIP", "Cannot make a call (not registered)");
00283         throw MMSError(0, "Cannot make a call (not registered)");
00284     }
00285 
00286     const char *cDomain;
00287     if((user.find("@") == string::npos) && this->defaultAccount >= 0) {
00288         cDomain = ((domain != "") ? domain.c_str() : this->accounts[defaultAccount].registrar.c_str());
00289         snprintf(tmp, 1024, "sip:%s@%s", user.c_str(), cDomain);
00290     }
00291     else
00292         snprintf(tmp, 1024, "sip:%s", user.c_str());
00293 
00294     if(!pj_thread_is_registered()) {
00295         MMSSipThread tInfo;
00296         pj_bzero(tInfo.desc, sizeof(pj_thread_desc));
00297         if(pj_thread_register("MMSSIP", tInfo.desc, &tInfo.thread) == PJ_SUCCESS) {
00298             this->threadInfo.push_back(tInfo);
00299         } else {
00300             DEBUGMSG("MMSSIP", "Error registering thread (pj_thread_register)");
00301             throw MMSError(0, "Error registering thread (pj_thread_register)");
00302         }
00303     }
00304 
00305     status = pjsua_verify_sip_url(tmp);
00306     if (status != PJ_SUCCESS) {
00307         DEBUGMSG("MMSSIP", "Invalid callee info sip:" + user + "@" + cDomain);
00308         throw MMSError(0, "Invalid callee info sip:" + user + "@" + cDomain);
00309     }
00310 
00311     uri = pj_str(tmp);
00312     status = pjsua_call_make_call(this->defaultAccount, &uri, 0, NULL, NULL, &call);
00313     if (status != PJ_SUCCESS) {
00314         DEBUGMSG("MMSSIP", "Error calling sip:" + user + "@" + cDomain);
00315         char buf[1024];
00316         pj_strerror(status, buf, sizeof(buf));
00317         throw MMSError(0, buf);
00318     }
00319 
00320     return call;
00321 }
00322 
00323 void MMSSip::hangup(int id) {
00324     DEBUGMSG("MMSSIP", "calling pjsua_call_hangup (id=%d)", id);
00325 
00326     if(!pj_thread_is_registered()) {
00327         MMSSipThread tInfo;
00328         pj_bzero(tInfo.desc, sizeof(pj_thread_desc));
00329         if(pj_thread_register("MMSSIP", tInfo.desc, &tInfo.thread) == PJ_SUCCESS) {
00330             this->threadInfo.push_back(tInfo);
00331         } else {
00332             DEBUGMSG("MMSSIP", "Error registering thread (pj_thread_register)");
00333             throw MMSError(0, "Error registering thread (pj_thread_register)");
00334         }
00335     }
00336 
00337     if(id != PJSUA_INVALID_ID) {
00338         // this is just a workaround, because sending 603/Decline didn't
00339         // work if state < PJSIP_INV_STATE_CONNECTING
00340         pjsua_call_info ci;
00341         pjsua_call_get_info(id, &ci);
00342         if(ci.state < PJSIP_INV_STATE_CONNECTING) {
00343             DEBUGMSG("MMSSIP", "answering with code 480");
00344             pjsua_call_answer(id, 480, NULL, NULL);
00345         }
00346         else
00347             pjsua_call_hangup(id, 0, NULL, NULL);
00348     }
00349     else
00350         pjsua_call_hangup_all();
00351 }
00352 
00353 void MMSSip::answer(int id) {
00354     DEBUGMSG("MMSSIP", "calling pjsua_call_answer");
00355 
00356     if(!pj_thread_is_registered()) {
00357         MMSSipThread tInfo;
00358         pj_bzero(tInfo.desc, sizeof(pj_thread_desc));
00359         if(pj_thread_register("MMSSIP", tInfo.desc, &tInfo.thread) == PJ_SUCCESS) {
00360             this->threadInfo.push_back(tInfo);
00361         } else {
00362             DEBUGMSG("MMSSIP", "Error registering thread (pj_thread_register)");
00363             throw MMSError(0, "Error registering thread (pj_thread_register)");
00364         }
00365     }
00366 
00367     pjsua_call_answer(id, 200, NULL, NULL);
00368 }
00369 
00370 void MMSSip::addBuddy(const string &name, const string &uri) {
00371     pjsua_buddy_config buddyCfg;
00372     pjsua_buddy_id     buddyId;
00373     pjsua_buddy_info   buddyInfo;
00374 
00375     if(!registered) {
00376         DEBUGMSG("MMSSIP", "Cannot add buddy (not registered)");
00377         throw MMSError(0, "Cannot add buddy (not registered)");
00378     }
00379 
00380     if(!pj_thread_is_registered()) {
00381         MMSSipThread tInfo;
00382         pj_bzero(tInfo.desc, sizeof(pj_thread_desc));
00383         if(pj_thread_register("MMSSIP", tInfo.desc, &tInfo.thread) == PJ_SUCCESS) {
00384             this->threadInfo.push_back(tInfo);
00385         } else {
00386             DEBUGMSG("MMSSIP", "Error registering thread (pj_thread_register)");
00387             throw MMSError(0, "Error registering thread (pj_thread_register)");
00388         }
00389     }
00390 
00391     pjsua_buddy_config_default(&buddyCfg);
00392     char buri[80];
00393     sprintf(buri, "sip:%s", uri.c_str());
00394     buddyCfg.uri = pj_str(buri);
00395     buddyCfg.subscribe = true;
00396     if(pjsua_buddy_add(&buddyCfg, &buddyId) == PJ_SUCCESS) {
00397         DEBUGMSG("MMSSIP", "successfully added buddy " + name);
00398         MMSSipBuddy buddy = {name, uri, BUDDY_UNKNOWN};
00399         buddies[buddyId] = buddy;
00400         if(pjsua_buddy_get_info(buddyId, &buddyInfo) == PJ_SUCCESS) {
00401             buddy.status = (MMSSipBuddyStatus)buddyInfo.status;
00402         }
00403         buddies[buddyId] = buddy;
00404         onBuddyState(buddyId);
00405     }
00406     else
00407         DEBUGMSG("MMSSIP", "failed to add buddy " + name);
00408 }
00409 
00410 MMSSipBuddy MMSSip::getBuddy(const int &id) {
00411     return this->buddies[id];
00412 }
00413 
00414 bool MMSSip::setSpeakerVolume(const unsigned int percent) {
00415     if(percent > 100) return false;
00416     if(!pjsua_conf_adjust_tx_level(0, (float)percent / 100) == PJ_SUCCESS) {
00417         DEBUGMSG("MMSSIP", "setting speaker volume failed");
00418         return false;
00419     }
00420     DEBUGMSG("MMSSIP", "setting speaker volume to %d%%", percent);
00421 
00422     return true;
00423 }
00424 
00425 int MMSSip::getSpeakerVolume() {
00426     unsigned int tx_level, rx_level;
00427     if(pjsua_conf_get_signal_level(0, &tx_level, &rx_level) == PJ_SUCCESS)
00428         return tx_level;
00429 
00430     return -1;
00431 }
00432 
00433 bool MMSSip::getAutoAnswer(int accountId) {
00434     try {
00435         MMSSipAccount acc = this->accounts[accountId];
00436         return acc.autoanswer;
00437     }
00438     catch(std::exception& e) {
00439         throw MMSError(0, e.what());
00440     }
00441 }
00442 
00443 void MMSSip::setAutoAnswer(int accountId, const bool value) {
00444     try {
00445         MMSSipAccount acc = this->accounts[accountId];
00446         acc.autoanswer = value;
00447     }
00448     catch(std::exception& e) {
00449         throw MMSError(0, e.what());
00450     }
00451 }
00452 
00453 /**
00454  * Register a .wav file as ringtone.
00455  *
00456  * @param   filename    [in]    wav-file to play
00457  *
00458  * @return  true, if successfull
00459  */
00460 bool MMSSip::registerRingtone(const string &filename) {
00461     pj_str_t tmp;
00462     if(pjsua_player_create(pj_cstr(&tmp, filename.c_str()), 0, &ringtonePlayer) == PJ_SUCCESS)
00463         return true;
00464 
00465     return false;
00466 }
00467 
00468 /**
00469  * Register a .wav file as busy-tone.
00470  *
00471  * @note    This file won't be looped.
00472  *
00473  * @param   filename    [in]    wav-file to play
00474  *
00475  * @return  true, if successfull
00476  */
00477 bool MMSSip::registerBusytone(const string &filename) {
00478     pj_str_t tmp;
00479     if(pjsua_player_create(pj_cstr(&tmp, filename.c_str()), PJMEDIA_FILE_NO_LOOP, &busytonePlayer) == PJ_SUCCESS)
00480         return true;
00481 
00482     return false;
00483 }
00484 
00485 /**
00486  * Register a .wav file as calling-tone.
00487  *
00488  * @param   filename    [in]    wav-file to play
00489  *
00490  * @return  true, if successfull
00491  */
00492 bool MMSSip::registerCallingtone(const string &filename) {
00493     pj_str_t tmp;
00494     if(pjsua_player_create(pj_cstr(&tmp, filename.c_str()), 0, &callingtonePlayer) == PJ_SUCCESS)
00495         return true;
00496 
00497     return false;
00498 }
00499 
00500 /* Callback called by the library upon receiving incoming call */
00501 static void onIncomingCall(pjsua_acc_id  accId,
00502                            pjsua_call_id callId,
00503                            pjsip_rx_data *rdata) {
00504     pjsua_call_info ci;
00505 
00506     PJ_UNUSED_ARG(rdata);
00507 
00508     /* if autoanswer is set, hangup all other calls */
00509     if(thiz->getAutoAnswer(accId)) {
00510         DEBUGMSG("MMSSIP", "Incoming call on account %d which has autoanswer feature turned on", accId);
00511         pjsua_call_id *ids;
00512         unsigned int count;
00513         if(pjsua_enum_calls(ids, &count) == PJ_SUCCESS) {
00514             for(unsigned int i = 0; i < count; ++i)
00515                 pjsua_call_hangup(ids[i], 481, NULL, NULL);
00516         }
00517         thiz->answer(callId);
00518     } else {
00519         pjsua_call_get_info(callId, &ci);
00520 
00521         DEBUGMSG("MMSSIP", "Incoming call from %.*s (id=%d)", (int)ci.remote_info.slen, ci.remote_info.ptr, callId);
00522 
00523         if(thiz && thiz->onCallIncoming)
00524             thiz->onCallIncoming->emit(callId, ci.remote_info.ptr, ci.last_status);
00525     }
00526 }
00527 
00528 /* Callback called by the library when call's state has changed */
00529 static void onCallState(pjsua_call_id callId, pjsip_event *e) {
00530     pjsua_call_info ci;
00531 
00532     PJ_UNUSED_ARG(e);
00533 
00534     pjsua_call_get_info(callId, &ci);
00535     DEBUGMSG("MMSSIP", "Call %d state=%d (%.*s)", callId, ci.state, (int)ci.state_text.slen, ci.state_text.ptr);
00536 
00537     switch(ci.state) {
00538         case PJSIP_INV_STATE_NULL:
00539             DEBUGMSG("MMSSIP", "onCallState: PJSIP_INV_STATE_NULL");
00540             break;
00541         case PJSIP_INV_STATE_CALLING:
00542             DEBUGMSG("MMSSIP", "onCallState: PJSIP_INV_STATE_CALLING");
00543             if(thiz && thiz->onCalling)
00544                 thiz->onCalling->emit(callId, ci.last_status);
00545             break;
00546         case PJSIP_INV_STATE_INCOMING:
00547             DEBUGMSG("MMSSIP", "onCallState: PJSIP_INV_STATE_INCOMING");
00548             if(ringtonePlayer != PJSUA_INVALID_ID &&
00549                 ci.role == PJSIP_ROLE_UAS &&
00550                 ci.media_status == PJSUA_CALL_MEDIA_NONE)
00551                 pjsua_conf_connect(pjsua_player_get_conf_port(ringtonePlayer), 0);
00552             break;
00553         case PJSIP_INV_STATE_EARLY:
00554             DEBUGMSG("MMSSIP", "onCallState: PJSIP_INV_STATE_EARLY");
00555             break;
00556         case PJSIP_INV_STATE_CONNECTING:
00557             DEBUGMSG("MMSSIP", "onCallState: PJSIP_INV_STATE_CONNECTING");
00558             if(callingtonePlayer != PJSUA_INVALID_ID &&
00559                 ci.role == PJSIP_ROLE_UAS &&
00560                 ci.media_status == PJSUA_CALL_MEDIA_NONE)
00561                 pjsua_conf_connect(pjsua_player_get_conf_port(callingtonePlayer), 0);
00562             break;
00563         case PJSIP_INV_STATE_CONFIRMED:
00564             DEBUGMSG("MMSSIP", "onCallState: PJSIP_INV_STATE_CONFIRMED");
00565             if(callingtonePlayer != PJSUA_INVALID_ID)
00566                 pjsua_conf_disconnect(pjsua_player_get_conf_port(callingtonePlayer), 0);
00567             if(thiz && thiz->onCallSuccessfull)
00568                 thiz->onCallSuccessfull->emit(callId, ci.last_status);
00569             break;
00570         case PJSIP_INV_STATE_DISCONNECTED:
00571             DEBUGMSG("MMSSIP", "lastStatusText: %s", ci.last_status_text);
00572             DEBUGMSG("MMSSIP", "onCallState: PJSIP_INV_STATE_DISCONNECTED");
00573             if(ringtonePlayer != PJSUA_INVALID_ID)
00574                 pjsua_conf_disconnect(pjsua_player_get_conf_port(ringtonePlayer), 0);
00575             if((ci.last_status == 486) && (busytonePlayer != PJSUA_INVALID_ID))
00576                 pjsua_conf_connect(pjsua_player_get_conf_port(busytonePlayer), 0);
00577             if(thiz && thiz->onCallDisconnected)
00578                 thiz->onCallDisconnected->emit(callId, ci.last_status);
00579             break;
00580         default:
00581 
00582             break;
00583     }
00584 }
00585 
00586 /* Callback called by the library when call's media state has changed */
00587 static void onCallMediaState(pjsua_call_id callId) {
00588     pjsua_call_info ci;
00589 
00590     if(ringtonePlayer != PJSUA_INVALID_ID)
00591         pjsua_conf_disconnect(pjsua_player_get_conf_port(ringtonePlayer), 0);
00592 
00593     pjsua_call_get_info(callId, &ci);
00594 
00595     if(ci.media_status == PJSUA_CALL_MEDIA_ACTIVE) {
00596         // When media is active, connect call to sound device.
00597         pjsua_conf_connect(ci.conf_slot, 0);
00598         pjsua_conf_connect(0, ci.conf_slot);
00599     }
00600 }
00601 
00602 static void onRegistrationState(pjsua_acc_id id) {
00603     pjsua_acc_info info;
00604 
00605     if(pjsua_acc_get_info(id, &info) == PJ_SUCCESS) {
00606         if(info.status == 200 && info.is_default) {
00607             registered = true;
00608             DEBUGMSG("MMSSIP", (registered ? "registered" : "not registered"));
00609         }
00610         DEBUGMSG("MMSSIP", "account: %s", info.acc_uri);
00611         DEBUGMSG("MMSSIP", "status: %d", info.status);
00612         DEBUGMSG("MMSSIP", "status_text: %s", info.status_text);
00613         DEBUGMSG("MMSSIP", "online_status: %d", info.online_status);
00614         DEBUGMSG("MMSSIP", "online_status_text: %s", info.online_status_text);
00615 
00616         /* set online if registration successfull and online status 0 */
00617         if(registered && !info.online_status) {
00618             if(pjsua_acc_set_online_status(id,  PJ_TRUE) == PJ_SUCCESS)
00619                 DEBUGMSG("MMSSIP", "Setting online status successfull");
00620             else
00621                 DEBUGMSG("MMSSIP", "Setting online status failed");
00622         }
00623     }
00624 }
00625 
00626 static void onBuddyState(pjsua_buddy_id id) {
00627     pjsua_buddy_info info;
00628 
00629     if(pjsua_buddy_get_info(id, &info) == PJ_SUCCESS) {
00630         if(thiz && thiz->onBuddyStatus)
00631             thiz->onBuddyStatus->emit(thiz->getBuddy(id));
00632     }
00633 }
00634 
00635 #endif /* __HAVE_MMSSIP__ */

Generated by doxygen