struct my_call_data *call_init_tonegen(pjsua_call_id call_id) { pj_pool_t *pool; struct my_call_data *cd; pjsua_call_info ci; if (call_id !=-1 ) { pjsua_call_get_info(call_id, &ci); if (ci.media_status != PJSUA_CALL_MEDIA_ACTIVE) return NULL; } pool = pjsua_pool_create("mycall", 512, 512); cd = PJ_POOL_ZALLOC_T(pool, struct my_call_data); cd->pool = pool; pjmedia_tonegen_create(cd->pool, 8000, 1, 160, 16, 0, &cd->tonegen); pjsua_conf_add_port(cd->pool, cd->tonegen, &cd->toneslot); if (call_id !=-1 ) { pjsua_conf_connect(cd->toneslot, ci.conf_slot); } if (accountSettings.localDTMF) { pjsua_conf_connect(cd->toneslot, 0); } if (call_id !=-1 ) { pjsua_call_set_user_data(call_id, (void*) cd); } return cd; }
struct my_call_data *call_init_tonegen(pjsua_call_id call_id) { pj_pool_t *pool; struct my_call_data *cd; pjsua_call_info ci; if (call_id !=-1 ) { pjsua_call_get_info(call_id, &ci); } pool = pjsua_pool_create("mycall", 512, 512); cd = PJ_POOL_ZALLOC_T(pool, struct my_call_data); cd->pool = pool; pjmedia_tonegen_create(cd->pool, 8000, 1, 160, 16, 0, &cd->tonegen); pjsua_conf_add_port(cd->pool, cd->tonegen, &cd->toneslot); if (call_id !=-1 ) { pjsua_conf_connect(cd->toneslot, ci.conf_slot); } pjsua_conf_connect(cd->toneslot, 0); if(call_id !=-1) { pjsua_call_set_user_data(call_id, (void*) cd); } return cd; }
void QVDoorcom::onCallState(int call_id, QString state) { if (call_id != active_call) { return; } qDebug() << "new state" << state; if (state == "DISCONNCTD") { popup->hide(); active_call = -1; // pjsua_conf_adjust_tx_level(0,0.0); } if (state == "CONFIRMED") { w_dooropen->show(); /* Create DTMF generator */ pjsua_call_info ci; qDebug() << "2" << pjmedia_tonegen_create(pj_pool, 16000, 1, 160, 16, 0, &pj_tonegen); qDebug() << "3" << pjsua_conf_add_port(pj_pool, pj_tonegen, &pj_toneslot); pjsua_call_get_info(call_id, &ci); qDebug() << "4" << pjsua_conf_connect(pj_toneslot, ci.conf_slot); /* Send DTMF code */ if (!code_accept.isEmpty()) { qDebug() << "accept code" << code_accept; pjmedia_tone_digit d[16]; unsigned i, count = code_accept.length(); if (count > PJ_ARRAY_SIZE(d)) { count = PJ_ARRAY_SIZE(d); } pj_bzero(d, sizeof(d)); for (i=0; i<count; i++) { d[i].digit = code_accept.at(i).toLatin1(); d[i].on_msec = 80; d[i].off_msec = 80; d[i].volume = 32767; } qDebug() << "before tonegen"; qDebug() << "tonegen result " << pjmedia_tonegen_play_digits(pj_tonegen, count, d, 0); dtmf_timer.start(); } } }
void init_ringback_tone(){ pj_status_t status; pj_str_t name; pjmedia_tone_desc tone[RINGBACK_CNT]; unsigned i; app_config.pool = pjsua_pool_create("pjsua-jni", 1000, 1000); app_config.ringback_slot=PJSUA_INVALID_ID; app_config.ringback_on = PJ_FALSE; app_config.ringback_cnt = 0; //Ringback name = pj_str((char *)"ringback"); status = pjmedia_tonegen_create2(app_config.pool, &name, 16000, 1, 320, 16, PJMEDIA_TONEGEN_LOOP, &app_config.ringback_port); if (status != PJ_SUCCESS){ goto on_error; } pj_bzero(&tone, sizeof(tone)); for (i=0; i<RINGBACK_CNT; ++i) { tone[i].freq1 = RINGBACK_FREQ1; tone[i].freq2 = RINGBACK_FREQ2; tone[i].on_msec = RINGBACK_ON; tone[i].off_msec = RINGBACK_OFF; } tone[RINGBACK_CNT-1].off_msec = RINGBACK_INTERVAL; pjmedia_tonegen_play(app_config.ringback_port, RINGBACK_CNT, tone, PJMEDIA_TONEGEN_LOOP); status = pjsua_conf_add_port(app_config.pool, app_config.ringback_port, &app_config.ringback_slot); if (status != PJ_SUCCESS){ goto on_error; } return; on_error :{ pj_pool_release(app_config.pool); } }
bool SipPhone::init_pjmedia() { #if 0 Logger::debug("SipPhone::init_pjmedia..."); #define CLOCK_RATE 8000 #define CHANNEL_COUNT 1 #define SAMPLES_PER_FRAME ((CLOCK_RATE * CHANNEL_COUNT * PJSUA_DEFAULT_AUDIO_FRAME_PTIME) / 1000) pj_status_t status = pjmedia_null_port_create(m_Pool, CLOCK_RATE, 1, SAMPLES_PER_FRAME, 16, &m_mediaPortSilence); if (status != PJ_SUCCESS) { Logger::error("pjmedia_null_port_create() failed (%s)", Helper::getPjStatusAsString(status).c_str()); return false; } status = pjsua_conf_add_port(m_Pool, m_mediaPortSilence, &m_mediaConfSilenceId); if (status != PJ_SUCCESS) { Logger::error("pjsua_conf_add_port() failed (%s)", Helper::getPjStatusAsString(status).c_str()); return false; } #endif return true; }
/***************************************************************************** * test: play simple ringback tone and hear it */ static void systest_play_tone(void) { /* Ringtones */ #define RINGBACK_FREQ1 440 /* 400 */ #define RINGBACK_FREQ2 480 /* 450 */ #define RINGBACK_ON 3000 /* 400 */ #define RINGBACK_OFF 4000 /* 200 */ #define RINGBACK_CNT 1 /* 2 */ #define RINGBACK_INTERVAL 4000 /* 2000 */ unsigned i, samples_per_frame; pjmedia_tone_desc tone[RINGBACK_CNT]; pj_pool_t *pool = NULL; pjmedia_port *ringback_port = NULL; enum gui_key key; int ringback_slot = -1; test_item_t *ti; pj_str_t name; const char *title = "Audio Tone Playback Test"; pj_status_t status; ti = systest_alloc_test_item(title); if (!ti) return; key = gui_msgbox(title, "This test will play simple ringback tone to " "the speaker. Please listen carefully for audio " "impairments such as stutter. You may need " "to let this test running for a while to " "make sure that everything is okay. Press " "OK to start, CANCEL to skip", WITH_OKCANCEL); if (key != KEY_OK) { ti->skipped = PJ_TRUE; return; } PJ_LOG(3,(THIS_FILE, "Running %s", title)); pool = pjsua_pool_create("ringback", 512, 512); samples_per_frame = systest.media_cfg.audio_frame_ptime * systest.media_cfg.clock_rate * systest.media_cfg.channel_count / 1000; /* Ringback tone (call is ringing) */ name = pj_str("ringback"); status = pjmedia_tonegen_create2(pool, &name, systest.media_cfg.clock_rate, systest.media_cfg.channel_count, samples_per_frame, 16, PJMEDIA_TONEGEN_LOOP, &ringback_port); if (status != PJ_SUCCESS) goto on_return; pj_bzero(&tone, sizeof(tone)); for (i=0; i<RINGBACK_CNT; ++i) { tone[i].freq1 = RINGBACK_FREQ1; tone[i].freq2 = RINGBACK_FREQ2; tone[i].on_msec = RINGBACK_ON; tone[i].off_msec = RINGBACK_OFF; } tone[RINGBACK_CNT-1].off_msec = RINGBACK_INTERVAL; status = pjmedia_tonegen_play(ringback_port, RINGBACK_CNT, tone, PJMEDIA_TONEGEN_LOOP); if (status != PJ_SUCCESS) goto on_return; status = pjsua_conf_add_port(pool, ringback_port, &ringback_slot); if (status != PJ_SUCCESS) goto on_return; status = pjsua_conf_connect(ringback_slot, 0); if (status != PJ_SUCCESS) goto on_return; key = gui_msgbox(title, "Ringback tone should be playing now in the " "speaker. Press OK to stop. ", WITH_OK); status = PJ_SUCCESS; on_return: if (ringback_slot != -1) pjsua_conf_remove_port(ringback_slot); if (ringback_port) pjmedia_port_destroy(ringback_port); if (pool) pj_pool_release(pool); if (status != PJ_SUCCESS) { systest_perror("Sorry we encounter error when initializing " "the tone generator: ", status); ti->success = PJ_FALSE; pj_strerror(status, ti->reason, sizeof(ti->reason)); } else { key = gui_msgbox(title, "Is the audio okay?", WITH_YESNO); ti->success = (key == KEY_YES); if (!ti->success) pj_ansi_strcpy(ti->reason, USER_ERROR); } return; }
QVDoorcom::QVDoorcom(QDomElement xml_desc, QString container, QWidget *parent) : QVElement(xml_desc,container,parent) { if (w < 1) { w = 1; } if (h < 1) { h = 1; } popup = 0; if (instance_count > 0) { w = h = 0; return; } instance_count = 1; doorcom = this; popup = new QVPopupFrame(parent); QDomElement e_server = xml_desc.firstChildElement("server"); QDomElement e_user = xml_desc.firstChildElement("user"); QDomElement e_password = xml_desc.firstChildElement("password"); if (e_server.isNull() || e_user.isNull() || e_password.isNull()) { qDebug() << "SIP client: insufficient auth info"; return; } QString s_server = e_server.text(); QString s_user = e_user.text(); QString s_password = e_password.text(); QDomElement e_caller = xml_desc.firstChildElement("source"); if (!e_caller.isNull()) { accepted_caller = e_caller.text(); } QDomElement e_accept = xml_desc.firstChildElement("accept"); if (!e_accept.isNull()) { code_accept = e_accept.text(); } QDomElement e_hangup = xml_desc.firstChildElement("hangup"); if (!e_hangup.isNull()) { code_hangup = e_hangup.text(); } QDomElement e_dooropen = xml_desc.firstChildElement("dooropen"); if (!e_dooropen.isNull()) { code_dooropen = e_dooropen.text(); } QFile f_doorbell; QString s_doorbell_name; bool doorbell_ok; bell_wav = 0; QDomElement e_doorbell = xml_desc.firstChildElement("ringtone"); if (!e_doorbell.isNull()) { s_doorbell_name = findFilePath(e_doorbell.text()); f_doorbell.setFileName(findFilePath(e_doorbell.text())); f_doorbell.open(QIODevice::ReadOnly); } if (!f_doorbell.isOpen()) { f_doorbell.setFileName(":/sounds/doorbell.wav"); f_doorbell.open(QIODevice::ReadOnly); } #ifndef DOORBELL_WAV QByteArray riff = f_doorbell.read(12); if (riff.length() < 12) { doorbell_ok = false; } else { if (!riff.startsWith("RIFF") || !riff.endsWith("WAVE")) { doorbell_ok = false; } } QByteArray fmthdr = f_doorbell.read(8); if (!fmthdr.startsWith("fmt")) { doorbell_ok = false; } uint32_t fmt_len; memcpy(&fmt_len,fmthdr.mid(4).data(),4); qDebug() << "fmt len" << fmt_len; if (fmt_len < 16) { doorbell_ok = false; } QByteArray fmt = f_doorbell.read(fmt_len); uint16_t audio_format; uint16_t num_channels; uint32_t sample_rate; uint32_t byte_rate; uint16_t block_align; uint16_t bits_per_sample; uint32_t bell_datalen; #if (BYTE_ORDER != __LITTLE_ENDIAN) #error Adapt endianness in __FILE__ #endif if (fmt.length() < fmt_len) { doorbell_ok = false; } else { memcpy(&audio_format,fmt.mid(0).data(),2); memcpy(&num_channels,fmt.mid(2).data(),2); memcpy(&sample_rate,fmt.mid(4).data(),4); memcpy(&byte_rate,fmt.mid(8).data(),4); memcpy(&block_align,fmt.mid(12).data(),2); memcpy(&bits_per_sample,fmt.mid(14).data(),2); } qDebug() << audio_format << "nch" << num_channels << "samplerate" << sample_rate << "byztera" << byte_rate << "blocka" << block_align << "bps" << bits_per_sample; if (audio_format != 0x0001) { doorbell_ok = false; } if (doorbell_ok) { QByteArray datahdr = f_doorbell.read(8); if (!datahdr.startsWith("data") || (datahdr.length() < 8)) { doorbell_ok = false; } else { memcpy(&bell_datalen,datahdr.mid(4).data(),4); } if (doorbell_ok && (bell_datalen > 0)) { QByteArray data = f_doorbell.read(bell_datalen); bell_wav = (char*)malloc(bell_datalen); if (bell_wav != 0) { memcpy(bell_wav,data.data(),bell_datalen); } } } #endif active_call = -1; QObject::connect(this,SIGNAL(incomingCall(int)),this,SLOT(onIncomingCall(int)),Qt::QueuedConnection); QObject::connect(this,SIGNAL(callState(int,QString)),this,SLOT(onCallState(int,QString)),Qt::QueuedConnection); QObject::connect(this,SIGNAL(callMediaState(int)),this,SLOT(onCallMediaState(int)),Qt::QueuedConnection); w_accept = new QVSvgWidget(":/icons/phone_call.svg",popup->content()); w_hangup = new QVSvgWidget(":/icons/phone_call_end.svg",popup->content()); w_dooropen = new QVSvgWidget(":/icons/door_open.svg",popup->content()); QObject::connect(w_accept,SIGNAL(clicked(double,double)),this,SLOT(onAcceptPressed())); QObject::connect(w_hangup,SIGNAL(clicked(double,double)),this,SLOT(onHangupPressed())); QObject::connect(w_dooropen,SIGNAL(clicked(double,double)),this,SLOT(onDoorOpenPressed())); hangup_timer.setSingleShot(true); hangup_timer.setInterval(800); QObject::connect(&hangup_timer,SIGNAL(timeout()),this,SLOT(onHangupTimer())); dtmf_timer.setSingleShot(true); dtmf_timer.setInterval(200); QObject::connect(&dtmf_timer,SIGNAL(timeout()),this,SLOT(onDTMFTimer())); /******* Init PJSUA ********/ pjsua_acc_id acc_id; pj_status_t status; /* Create pjsua first! */ status = pjsua_create(); if (status != PJ_SUCCESS) { qDebug() << "Cannot create PJSUA SIP client, cause:" << status; return; } /* Init pjsua */ pjsua_config cfg; pjsua_logging_config log_cfg; pjsua_media_config media_cfg; pjsua_config_default(&cfg); cfg.cb.on_incoming_call = &on_incoming_call; cfg.cb.on_call_media_state = &on_call_media_state; cfg.cb.on_call_state = &on_call_state; pjsua_logging_config_default(&log_cfg); log_cfg.console_level = 1; pjsua_media_config_default(&media_cfg); media_cfg.clock_rate = 8000; media_cfg.ec_tail_len = 0; status = pjsua_init(&cfg, &log_cfg, &media_cfg); if (status != PJ_SUCCESS) { qDebug() << "Cannot init PJSUA SIP client, cause: " << status; return; } /* Add UDP transport. */ pjsua_transport_config transport_cfg; pjsua_transport_config_default(&transport_cfg); transport_cfg.port = 5060; status = pjsua_transport_create(PJSIP_TRANSPORT_UDP, &transport_cfg, NULL); if (status != PJ_SUCCESS) { qDebug() << "Cannot init PJSUA UDP transport, cause: " << status; return; } /* Initialization is done, now start pjsua */ status = pjsua_start(); if (status != PJ_SUCCESS) { qDebug() << "Cannot start PJSUA SIP client, cause: " << status; return; } /* Register to SIP server by creating SIP account. */ pjsua_acc_config acc_cfg; pjsua_acc_config_default(&acc_cfg); QString s_id = "sip:" + s_user + "@" + s_server; QString s_uri = "sip:" + s_server; acc_cfg.cred_count = 1; acc_cfg.cred_info[0].realm = pj_str(strdup(s_server.toLocal8Bit().data())); acc_cfg.cred_info[0].scheme = pj_str("digest"); acc_cfg.cred_info[0].username = pj_str(strdup(s_user.toLocal8Bit().data())); acc_cfg.cred_info[0].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD; acc_cfg.cred_info[0].data = pj_str(strdup(s_password.toLocal8Bit().data())); acc_cfg.id = pj_str(strdup(s_id.toLocal8Bit().data())); acc_cfg.reg_uri = pj_str(strdup(s_uri.toLocal8Bit().data())); status = pjsua_acc_add(&acc_cfg, PJ_TRUE, &acc_id); if (status != PJ_SUCCESS) { qDebug() << "PJSUA auth data invalid, cause: " << status; return; } qDebug() << "PJSUA ports" << pjsua_conf_get_active_ports(); pjsua_conf_port_info info; pjsua_conf_get_port_info (0, &info); qDebug() << pj2qstring(info.name); // pjsua_conf_adjust_tx_level(0,0.0); pj_caching_pool_init(&pj_cpool, &pj_pool_factory_default_policy, 0); pj_pool = pjsua_pool_create("qvisu", 8192, 8192); #ifndef DOORBELL_WAV if (doorbell_ok && (bell_wav != 0)) { status = pjmedia_mem_player_create(pj_pool, bell_wav, bell_datalen, sample_rate, num_channels, 16384, bits_per_sample, 0,//PJMEDIA_MEM_NO_LOOP, &bell_file_port); qDebug() << "Bell memory player" << status; status = pjsua_conf_add_port(pj_pool,bell_file_port,&bell_port_id); qDebug() << "bell file add status" << status << "id" << bell_port_id; status = pjmedia_mem_player_set_eof_cb (bell_file_port, 0, &on_file_played); } else { bell_file_port = 0; } #else qDebug() << "Doorbell file" << s_doorbell_name; if (s_doorbell_name.isEmpty()) { bell_file_port = 0; } else { /* Create file media port for doorbell from the WAV file */ status = pjmedia_wav_player_port_create(pj_pool, /* memory pool */ strdup(s_doorbell_name.toUtf8().data()), /* file to play */ 20, /* ptime. */ PJMEDIA_FILE_NO_LOOP, /* flags */ 0, /* default buffer */ &bell_file_port/* returned port */ ); if (status != PJ_SUCCESS) { qDebug() << "Cannot open wav file" << status; bell_file_port = 0; } } if (bell_file_port != 0) { status = pjsua_conf_add_port(pj_pool,bell_file_port,&bell_port_id); qDebug() << "bell file add status" << status << "id" << bell_port_id; status = pjmedia_wav_player_set_eof_cb (bell_file_port, 0, &on_file_played); if (status != PJ_SUCCESS) { qDebug() << "Cannot register callback"; bell_file_port = 0; } } #endif }