Subversion Repositories tpanel

Rev

Rev 140 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 140 Rev 141
Line 37... Line 37...
37
#define REGISTER_THREAD() \
37
#define REGISTER_THREAD() \
38
if(!pj_thread_is_registered()) {\
38
if(!pj_thread_is_registered()) {\
39
    pj_thread_register(NULL, _desc_, &_thread_);\
39
    pj_thread_register(NULL, _desc_, &_thread_);\
40
}
40
}
41
 
41
 
-
 
42
#if __cplusplus < 201402L
-
 
43
#   error "This module requires at least C++14 standard!"
-
 
44
#else
-
 
45
#   if __cplusplus < 201703L
-
 
46
#       include <experimental/filesystem>
-
 
47
        namespace fs = std::experimental::filesystem;
-
 
48
#       warning "Support for C++14 and experimental filesystem will be removed in a future version!"
-
 
49
#   else
-
 
50
#       include <filesystem>
-
 
51
#       ifdef __ANDROID__
-
 
52
            namespace fs = std::__fs::filesystem;
-
 
53
#       else
-
 
54
            namespace fs = std::filesystem;
-
 
55
#       endif
-
 
56
#   endif
-
 
57
#endif
-
 
58
 
42
using std::string;
59
using std::string;
43
using std::vector;
60
using std::vector;
44
using std::to_string;
61
using std::to_string;
45
using std::atomic;
62
using std::atomic;
-
 
63
using std::thread;
46
 
64
 
47
TSIPClient *TSIPClient::mMyself{nullptr};
65
TSIPClient *TSIPClient::mMyself{nullptr};
48
TSIPClient::pjsua_app_config TSIPClient::mAppConfig;
66
TSIPClient::pjsua_app_config TSIPClient::mAppConfig;
49
pjsua_call_id TSIPClient::mCurrentCall{PJSUA_INVALID_ID};
67
pjsua_call_id TSIPClient::mCurrentCall{PJSUA_INVALID_ID};
50
atomic<bool> TSIPClient::mRefreshRun{false};
68
atomic<bool> TSIPClient::mRefreshRun{false};
-
 
69
bool TSIPClient::mPhoneRingInit{false};
-
 
70
TSIPClient::ringtone_port_info_t TSIPClient::mRingtonePortInfo;
51
 
71
 
52
// The module instance.
72
// The module instance.
53
pjsip_module TSIPClient::mod_default_handler =
73
pjsip_module TSIPClient::mod_default_handler =
54
{
74
{
55
    NULL, NULL,                             // prev, next.
75
    NULL, NULL,                             // prev, next.
Line 614... Line 634...
614
 
634
 
615
void TSIPClient::cleanUp()
635
void TSIPClient::cleanUp()
616
{
636
{
617
    DECL_TRACER("TSIPClient::cleanUp()");
637
    DECL_TRACER("TSIPClient::cleanUp()");
618
 
638
 
-
 
639
    if (mPhoneRingInit && mRingtonePortInfo.pool)
-
 
640
    {
-
 
641
        pj_pool_release(mRingtonePortInfo.pool);
-
 
642
        mRingtonePortInfo.pool = nullptr;
-
 
643
        mPhoneRingInit = false;
-
 
644
    }
-
 
645
 
619
    pjsua_destroy();
646
    pjsua_destroy();
620
    mAccountID = 0;
647
    mAccountID = 0;
621
    mLine = PJSUA_INVALID_ID;
648
    mLine = PJSUA_INVALID_ID;
622
    mCurrentCall = PJSUA_INVALID_ID;
649
    mCurrentCall = PJSUA_INVALID_ID;
623
 
650
 
Line 655... Line 682...
655
 
682
 
656
    if (dest.find("sip:") == string::npos)
683
    if (dest.find("sip:") == string::npos)
657
        sUri = "sip:";
684
        sUri = "sip:";
658
 
685
 
659
    sUri += dest;
686
    sUri += dest;
-
 
687
 
-
 
688
    if (sUri.find("@") == string::npos)
-
 
689
        sUri += "@" + TConfig::getSIPproxy();
-
 
690
 
660
    pj_str_t uri = pj_str((char *)sUri.c_str());
691
    pj_str_t uri = pj_str((char *)sUri.c_str());
661
    REGISTER_THREAD();
692
    REGISTER_THREAD();
662
    pjsua_call_id cid = PJSUA_INVALID_ID;
693
    pjsua_call_id cid = PJSUA_INVALID_ID;
663
    pjsua_call_setting call_opt;
694
    pjsua_call_setting call_opt;
664
 
695
 
Line 673... Line 704...
673
        return false;
704
        return false;
674
    }
705
    }
675
 
706
 
676
    mLine = cid;
707
    mLine = cid;
677
    mLastCall = dest;
708
    mLastCall = dest;
678
    sendConnectionStatus(SIP_TRYING, mLine);
-
 
679
    return true;
709
    return true;
680
}
710
}
681
 
711
 
682
bool TSIPClient::pickup(pjsua_call_id call)
712
bool TSIPClient::pickup(pjsua_call_id call)
683
{
713
{
Line 702... Line 732...
702
        MSG_ERROR("Couldn't answer with call ID " << call);
732
        MSG_ERROR("Couldn't answer with call ID " << call);
703
        sendConnectionStatus(SIP_ERROR, call);
733
        sendConnectionStatus(SIP_ERROR, call);
704
        return false;
734
        return false;
705
    }
735
    }
706
 
736
 
707
    sendConnectionStatus(SIP_CONNECTED, call);
-
 
708
    mLine = call;
737
    mLine = call;
709
    return true;
738
    return true;
710
}
739
}
711
 
740
 
712
bool TSIPClient::terminate(int id)
741
bool TSIPClient::terminate(int id)
Line 777... Line 806...
777
        MSG_ERROR("Call couldn't be resumed!");
806
        MSG_ERROR("Call couldn't be resumed!");
778
        sendConnectionStatus(SIP_ERROR, cid);
807
        sendConnectionStatus(SIP_ERROR, cid);
779
        return false;
808
        return false;
780
    }
809
    }
781
 
810
 
782
    sendConnectionStatus(SIP_CONNECTED, cid);
-
 
783
    mLine = id;
811
    mLine = id;
784
    return true;
812
    return true;
785
}
813
}
786
 
814
 
787
bool TSIPClient::sendDTMF(string& dtmf)
815
bool TSIPClient::sendDTMF(string& dtmf)
Line 938... Line 966...
938
 
966
 
939
    if (!gPageManager)
967
    if (!gPageManager)
940
        return;
968
        return;
941
 
969
 
942
    if (state == SIP_RINGING && TConfig::getSIPiphone() && gPageManager->getShowPhoneDialog())
970
    if (state == SIP_RINGING && TConfig::getSIPiphone() && gPageManager->getShowPhoneDialog())
-
 
971
    {
-
 
972
        pjsua_call_info ci;
-
 
973
 
943
        gPageManager->getShowPhoneDialog()(true);
974
        gPageManager->getShowPhoneDialog()(true);
-
 
975
        pjsua_call_get_info(id, &ci);
-
 
976
        string number;
-
 
977
        number.assign(ci.remote_info.ptr, ci.remote_info.slen);
-
 
978
        size_t pos;
-
 
979
 
-
 
980
        if ((pos = number.find("\"")) != string::npos)
-
 
981
        {
-
 
982
            size_t pos2 = number.find("\"", pos + 1);
-
 
983
 
-
 
984
            if (pos2 != string::npos)
-
 
985
                number = number.substr(pos + 1, pos2 - pos - 1);
-
 
986
            else
-
 
987
                number = number.substr(pos + 1);
-
 
988
        }
-
 
989
        else if ((pos = number.find("sip:")) != string::npos)
-
 
990
        {
-
 
991
            size_t pos2 = number.find("@");
-
 
992
 
-
 
993
            if (pos2 != string::npos && pos2 > pos)
-
 
994
                number = number.substr(pos + 4, pos2 - (pos + 4));
-
 
995
            else
-
 
996
                number = number.substr(pos + 4);
-
 
997
        }
-
 
998
 
-
 
999
        gPageManager->getSetPhoneNumber()(number);
-
 
1000
        gPageManager->getSetPhoneState()(SIP_RINGING, id);
-
 
1001
    }
944
 
1002
 
945
    vector<string> cmds;
1003
    vector<string> cmds;
946
    cmds.push_back("CALL");
1004
    cmds.push_back("CALL");
947
 
1005
 
948
    switch(state)
1006
    switch(state)
Line 966... Line 1024...
966
 
1024
 
967
    if (gPageManager->getSetPhoneState())
1025
    if (gPageManager->getSetPhoneState())
968
        gPageManager->getSetPhoneState()(state, id);
1026
        gPageManager->getSetPhoneState()(state, id);
969
}
1027
}
970
 
1028
 
-
 
1029
void TSIPClient::runRinger()
-
 
1030
{
-
 
1031
    DECL_TRACER("TSIPClient::runRinger()");
-
 
1032
 
-
 
1033
    init_ringtone_player();
-
 
1034
 
-
 
1035
    if (start_ring_tone() != PJ_SUCCESS)
-
 
1036
    {
-
 
1037
        //FIXME:: Add code to free the pool
-
 
1038
        return;
-
 
1039
    }
-
 
1040
}
-
 
1041
 
-
 
1042
void TSIPClient::init_ringtone_player()
-
 
1043
{
-
 
1044
    DECL_TRACER("TSIPClient::init_ringtone_player()");
-
 
1045
 
-
 
1046
    int file_slot;
-
 
1047
    pj_pool_t *pool;
-
 
1048
    pjmedia_port *file_port;
-
 
1049
    pj_status_t status;
-
 
1050
 
-
 
1051
    if (mPhoneRingInit)
-
 
1052
        return;
-
 
1053
 
-
 
1054
    string tone = TConfig::getProjectPath() + "/__system/graphics/sounds/ringtone.wav";
-
 
1055
    MSG_DEBUG("Testing for sound file: " << tone);
-
 
1056
 
-
 
1057
    if (!fs::exists(tone))
-
 
1058
    {
-
 
1059
        tone = TConfig::getProjectPath() + "/sounds/ringtone.wav";
-
 
1060
        MSG_DEBUG("Testing for sound file: " << tone);
-
 
1061
 
-
 
1062
        if (!fs::exists(tone))
-
 
1063
        {
-
 
1064
            MSG_ERROR("Couldn't find any ringtone sound file!");
-
 
1065
            return;
-
 
1066
        }
-
 
1067
    }
-
 
1068
 
-
 
1069
    pool = pjsua_pool_create("wav", 4000, 4000);
-
 
1070
    status = pjmedia_wav_player_port_create(pool, tone.c_str(), 0, 0, 0, &file_port);
-
 
1071
 
-
 
1072
    if (status != PJ_SUCCESS)
-
 
1073
    {
-
 
1074
        MSG_ERROR("Error creating WAV player port: " << status);
-
 
1075
        return;
-
 
1076
    }
-
 
1077
 
-
 
1078
    status = pjsua_conf_add_port(pool, file_port, &file_slot);
-
 
1079
 
-
 
1080
    if (status != PJ_SUCCESS) {
-
 
1081
        MSG_ERROR("Error adding port to conference: " << status);
-
 
1082
        return;
-
 
1083
    }
-
 
1084
 
-
 
1085
    mRingtonePortInfo.ring_on = PJ_FALSE;
-
 
1086
    mRingtonePortInfo.ring_slot = file_slot;
-
 
1087
    mRingtonePortInfo.ring_port = file_port;
-
 
1088
    mRingtonePortInfo.pool = pool;
-
 
1089
    mPhoneRingInit = true;
-
 
1090
}
-
 
1091
 
-
 
1092
pj_status_t TSIPClient::start_ring_tone()
-
 
1093
{
-
 
1094
    DECL_TRACER("TSIPClient::start_ring_tone() ");
-
 
1095
 
-
 
1096
    pj_status_t status;
-
 
1097
 
-
 
1098
    if (mRingtonePortInfo.ring_on)
-
 
1099
    {
-
 
1100
        MSG_DEBUG("Ringtone port already connected");
-
 
1101
        return PJ_SUCCESS;
-
 
1102
    }
-
 
1103
 
-
 
1104
    MSG_DEBUG("Starting ringtone");
-
 
1105
    status = pjsua_conf_connect(mRingtonePortInfo.ring_slot, 0);
-
 
1106
    mRingtonePortInfo.ring_on = PJ_TRUE;
-
 
1107
 
-
 
1108
    if (status != PJ_SUCCESS)
-
 
1109
    {
-
 
1110
        MSG_ERROR("Error connecting ringtone port: " << status);
-
 
1111
    }
-
 
1112
 
-
 
1113
    return status;
-
 
1114
}
-
 
1115
 
-
 
1116
pj_status_t TSIPClient::stop_ring_tone()
-
 
1117
{
-
 
1118
    DECL_TRACER("TSIPClient::stop_ring_tone()");
-
 
1119
 
-
 
1120
    pj_status_t status;
-
 
1121
 
-
 
1122
    if (!mRingtonePortInfo.ring_on)
-
 
1123
    {
-
 
1124
        MSG_DEBUG("Ringtone port already disconnected");
-
 
1125
        return PJ_SUCCESS;
-
 
1126
    }
-
 
1127
 
-
 
1128
    MSG_DEBUG("Stopping ringtone");
-
 
1129
    status = pjsua_conf_disconnect(mRingtonePortInfo.ring_slot, 0);
-
 
1130
    mRingtonePortInfo.ring_on = PJ_FALSE;
-
 
1131
 
-
 
1132
    if (status != PJ_SUCCESS)
-
 
1133
    {
-
 
1134
        MSG_ERROR("Error disconnecting ringtone port" << status);
-
 
1135
    }
-
 
1136
 
-
 
1137
    return status;
-
 
1138
}
-
 
1139
 
971
/*******************************************************************************
1140
/*******************************************************************************
972
 * All the following functions are static callback functions.
1141
 * All the following functions are static callback functions.
973
 * The following functions are called by the PJSUA-library for different
1142
 * The following functions are called by the PJSUA-library for different
974
 * events.
1143
 * events.
975
 ******************************************************************************/
1144
 ******************************************************************************/
Line 997... Line 1166...
997
    if (mAppConfig.call_data[call_id].ringback_on)
1166
    if (mAppConfig.call_data[call_id].ringback_on)
998
        return;
1167
        return;
999
 
1168
 
1000
    mAppConfig.call_data[call_id].ringback_on = PJ_TRUE;
1169
    mAppConfig.call_data[call_id].ringback_on = PJ_TRUE;
1001
 
1170
 
1002
    if (++mAppConfig.ringback_cnt==1 && mAppConfig.ringback_slot!=PJSUA_INVALID_ID)
1171
    if (++mAppConfig.ringback_cnt == 1 && mAppConfig.ringback_slot != PJSUA_INVALID_ID)
1003
    {
1172
    {
1004
        pjsua_conf_connect(mAppConfig.ringback_slot, 0);
1173
        pjsua_conf_connect(mAppConfig.ringback_slot, 0);
1005
    }
1174
    }
1006
}
1175
}
1007
 
1176
 
Line 1027... Line 1196...
1027
 
1196
 
1028
    if (mAppConfig.call_data[call_id].ring_on)
1197
    if (mAppConfig.call_data[call_id].ring_on)
1029
    {
1198
    {
1030
        mAppConfig.call_data[call_id].ring_on = PJ_FALSE;
1199
        mAppConfig.call_data[call_id].ring_on = PJ_FALSE;
1031
 
1200
 
1032
        pj_assert(mAppConfig.ring_cnt>0);
1201
        pj_assert(mAppConfig.ring_cnt > 0);
1033
 
1202
 
1034
        if (--mAppConfig.ring_cnt == 0 && mAppConfig.ring_slot != PJSUA_INVALID_ID)
1203
        if (--mAppConfig.ring_cnt == 0 && mAppConfig.ring_slot != PJSUA_INVALID_ID)
1035
        {
1204
        {
1036
            pjsua_conf_disconnect(mAppConfig.ring_slot, 0);
1205
            pjsua_conf_disconnect(mAppConfig.ring_slot, 0);
1037
            pjmedia_tonegen_rewind(mAppConfig.ring_port);
1206
            pjmedia_tonegen_rewind(mAppConfig.ring_port);
Line 1049... Line 1218...
1049
    if (mAppConfig.call_data[call_id].ring_on)
1218
    if (mAppConfig.call_data[call_id].ring_on)
1050
        return;
1219
        return;
1051
 
1220
 
1052
    mAppConfig.call_data[call_id].ring_on = PJ_TRUE;
1221
    mAppConfig.call_data[call_id].ring_on = PJ_TRUE;
1053
 
1222
 
1054
    if (++mAppConfig.ring_cnt==1 && mAppConfig.ring_slot != PJSUA_INVALID_ID)
1223
    if (++mAppConfig.ring_cnt == 1 && mAppConfig.ring_slot != PJSUA_INVALID_ID)
1055
    {
1224
    {
1056
        pjsua_conf_connect(mAppConfig.ring_slot, 0);
1225
        pjsua_conf_connect(mAppConfig.ring_slot, 0);
1057
    }
1226
    }
1058
}
1227
}
1059
 
1228
 
Line 1167... Line 1336...
1167
    sendConnectionStatus(SIP_RINGING, call_id);
1336
    sendConnectionStatus(SIP_RINGING, call_id);
1168
 
1337
 
1169
    /* Automatically answer incoming calls with 200/OK */
1338
    /* Automatically answer incoming calls with 200/OK */
1170
    if (gPageManager && gPageManager->getPHNautoanswer() && mMyself)
1339
    if (gPageManager && gPageManager->getPHNautoanswer() && mMyself)
1171
        mMyself->pickup(call_id);
1340
        mMyself->pickup(call_id);
-
 
1341
    else if (mMyself)
-
 
1342
        mMyself->runRinger();
1172
}
1343
}
1173
 
1344
 
1174
/* Callback called by the library when call's state has changed */
1345
/* Callback called by the library when call's state has changed */
1175
void TSIPClient::on_call_state(pjsua_call_id call_id, pjsip_event *e)
1346
void TSIPClient::on_call_state(pjsua_call_id call_id, pjsip_event *e)
1176
{
1347
{
Line 1183... Line 1354...
1183
    if (ci.state == PJSIP_INV_STATE_DISCONNECTED)
1354
    if (ci.state == PJSIP_INV_STATE_DISCONNECTED)
1184
    {
1355
    {
1185
        /* Stop all ringback for this call */
1356
        /* Stop all ringback for this call */
1186
        ring_stop(call_id);
1357
        ring_stop(call_id);
1187
 
1358
 
-
 
1359
        if (mPhoneRingInit)
-
 
1360
            stop_ring_tone();
-
 
1361
 
1188
        /* Cancel duration timer, if any */
1362
        /* Cancel duration timer, if any */
1189
        if (mAppConfig.call_data[call_id].timer.id != PJSUA_INVALID_ID)
1363
        if (mAppConfig.call_data[call_id].timer.id != PJSUA_INVALID_ID)
1190
        {
1364
        {
1191
            app_call_data *cd = &mAppConfig.call_data[call_id];
1365
            app_call_data *cd = &mAppConfig.call_data[call_id];
1192
            pjsip_endpoint *endpt = pjsua_get_pjsip_endpt();
1366
            pjsip_endpoint *endpt = pjsua_get_pjsip_endpt();
Line 1252... Line 1426...
1252
 
1426
 
1253
            /* Start ringback for 180 for UAC unless there's SDP in 180 */
1427
            /* Start ringback for 180 for UAC unless there's SDP in 180 */
1254
            if (ci.role == PJSIP_ROLE_UAC && code == 180 && msg->body == NULL && ci.media_status == PJSUA_CALL_MEDIA_NONE)
1428
            if (ci.role == PJSIP_ROLE_UAC && code == 180 && msg->body == NULL && ci.media_status == PJSUA_CALL_MEDIA_NONE)
1255
            {
1429
            {
1256
                ringback_start(call_id);
1430
                ringback_start(call_id);
1257
                sendConnectionStatus(SIP_RINGING, call_id);
-
 
1258
            }
1431
            }
1259
 
1432
 
1260
            string dbgMsg;
1433
            string dbgMsg;
1261
            string dbgCode;
1434
            string dbgCode;
1262
 
1435
 
Line 1274... Line 1447...
1274
 
1447
 
1275
            if (ci.state_text.slen > 0)
1448
            if (ci.state_text.slen > 0)
1276
                dbgMsg.assign(ci.state_text.ptr, ci.state_text.slen);
1449
                dbgMsg.assign(ci.state_text.ptr, ci.state_text.slen);
1277
 
1450
 
1278
            MSG_DEBUG("Call " << call_id << " state changed to " << dbgMsg);
1451
            MSG_DEBUG("Call " << call_id << " state changed to " << dbgMsg);
-
 
1452
 
-
 
1453
            if (ci.state == PJSIP_INV_STATE_CONNECTING || ci.state == PJSIP_INV_STATE_CALLING)
-
 
1454
                sendConnectionStatus(SIP_TRYING, call_id);
-
 
1455
            else if (ci.state == PJSIP_INV_STATE_INCOMING)
-
 
1456
                sendConnectionStatus(SIP_RINGING, call_id);
-
 
1457
            else if (ci.state == PJSIP_INV_STATE_CONFIRMED)
-
 
1458
            {
-
 
1459
                ring_stop(call_id);
-
 
1460
 
-
 
1461
                if (mPhoneRingInit)
-
 
1462
                    stop_ring_tone();
-
 
1463
 
-
 
1464
                sendConnectionStatus(SIP_CONNECTED, call_id);
-
 
1465
            }
1279
        }
1466
        }
1280
 
1467
 
1281
        if (mCurrentCall == PJSUA_INVALID_ID)
1468
        if (mCurrentCall == PJSUA_INVALID_ID)
1282
            mCurrentCall = call_id;
1469
            mCurrentCall = call_id;
1283
    }
1470
    }