示例#1
0
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;
}
示例#2
0
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;
}
示例#3
0
/* Callback called by PJSUA when call's media state has changed */
static void on_call_media_state(pjsua_call_id call_id) {
    qDebug() << "Call media state";
    pjsua_call_info ci;
    if (pjsua_call_get_info(call_id, &ci) != PJ_SUCCESS) {
        return;
    }
    pjsua_conf_connect(ci.conf_slot, 0);
    pjsua_conf_connect(0, ci.conf_slot);
}
示例#4
0
文件: main.c 项目: xgenvn/tinysip
/* Callback called by the library when call's media state has changed */
static void on_call_media_state(pjsua_call_id call_id) {
    pjsua_call_info ci;

    pjsua_call_get_info(call_id, &ci);

    if (ci.media_status == PJSUA_CALL_MEDIA_ACTIVE) {
        // When media is active, connect call to sound device.
        pjsua_conf_connect(ci.conf_slot, 0);
        pjsua_conf_connect(0, ci.conf_slot);
    }
}
示例#5
0
/*
 * Callback on media state changed event.
 * The action may connect the call to sound device, to file, or
 * to loop the call.
 */
static void on_call_media_state (pjsua_call_id call_id)
{
    pjsua_call_info call_info;

    pjsua_call_get_info (call_id, &call_info);

    if (call_info.media_status == PJSUA_CALL_MEDIA_ACTIVE) {
        pjsua_conf_connect (call_info.conf_slot, 0);
        pjsua_conf_connect (0, call_info.conf_slot);
    }
}
示例#6
0
void QPhoneHandler::onCallMediaState(qpjsua::CallInfo aCallInfo)
{
    callInfoOut(aCallInfo);

    if(aCallInfo.getMediaStatus() == PJSUA_CALL_MEDIA_ACTIVE) {
        pjsua_conf_connect(0, aCallInfo.getConferenceSlot());
        pjsua_conf_connect(aCallInfo.getConferenceSlot(), 0);

       // view->setButtonText("Auflegen");
      //  connect(view, SIGNAL(accept()), SLOT(onHangup()));
    }
}
示例#7
0
//----------------------------------------------------------------------
void SipPhone::callMediaStateCb(pjsua_call_id call_id)
{
    pjsua_call_info ci;

    pjsua_call_get_info(call_id, &ci);
    if (ci.media_status == PJSUA_CALL_MEDIA_ACTIVE) 
    {
        // When media is active, connect call to sound device.
        pjsua_conf_connect(ci.conf_slot, 0);
        pjsua_conf_connect(0, ci.conf_slot);
    }
    LogInfo info(LogInfo::STATUS_DEBUG, "pjsip", 0, "Call-media-state changed to "+QString::number(ci.state));
    self_->signalLogData(info);
}
示例#8
0
static void ui_conf_connect(char menuin[])
{
    char tmp[10], src_port[10], dst_port[10];
    pj_status_t status;
    int cnt;
    const char *src_title, *dst_title;

    cnt = sscanf(menuin, "%s %s %s", tmp, src_port, dst_port);

    if (cnt != 3) {
	ui_conf_list();

	src_title = (menuin[1]=='c'? "Connect src port #":
				     "Disconnect src port #");
	dst_title = (menuin[1]=='c'? "To dst port #":"From dst port #");

	if (!simple_input(src_title, src_port, sizeof(src_port)))
	    return;

	if (!simple_input(dst_title, dst_port, sizeof(dst_port)))
	    return;
    }

    if (menuin[1]=='c') {
	status = pjsua_conf_connect(my_atoi(src_port), my_atoi(dst_port));
    } else {
	status = pjsua_conf_disconnect(my_atoi(src_port), my_atoi(dst_port));
    }
    if (status == PJ_SUCCESS) {
	puts("Success");
    } else {
	puts("ERROR!!");
    }
}
示例#9
0
// helper for creating call-media-player
static void create_player(pjsua_call_id call_id)
{
	// get call infos
	pjsua_call_info ci; 
	pjsua_call_get_info(call_id, &ci);
	
	pj_str_t name;
	pj_status_t status = PJ_ENOTFOUND;
	
	log_message("Creating player ... ");
	
	// create player for playback media		
	if (app_cfg.wav_file) {
		status = pjsua_player_create(pj_cstr(&name, app_cfg.wav_file), 0, &play_id);
	} else {
		status = pjsua_player_create(pj_cstr(&name, app_cfg.tts_file), 0, &play_id);
	}
	if (status != PJ_SUCCESS) error_exit("Error playing sound-playback", status);
		
	// connect active call to media player
	pjsua_conf_connect(pjsua_player_get_conf_port(play_id), ci.conf_slot);
	
	// get media port (play_port) from play_id
    status = pjsua_player_get_port(play_id, &play_port);
	if (status != PJ_SUCCESS) error_exit("Error getting sound player port", status);
	
	// register media finished callback	
    status = pjmedia_wav_player_set_eof_cb(play_port, NULL, &on_media_finished);
	if (status != PJ_SUCCESS) error_exit("Error adding sound-playback callback", status);
	
	log_message("Done.\n");
}
示例#10
0
//----------------------------------------------------------------------
bool SipPhone::addCallToConference(const int &call_src, const int &call_dest)
{
    int src = call_src;
    int dest = call_dest;

    if (src == -1 || dest == -1)
    {
        LogInfo info(LogInfo::STATUS_ERROR, "pjsip", 0, "Error: one of the selected calls does NOT exist!");
        signalLogData(info);
        return false;
    }

    pjsua_call_info src_ci, dest_ci;

    pjsua_call_get_info(src,&src_ci);
    pjsua_call_get_info(dest,&dest_ci);

    pj_status_t status =  pjsua_conf_connect(src_ci.conf_slot,dest_ci.conf_slot);
    if (status != PJ_SUCCESS)
    {
        LogInfo info(LogInfo::STATUS_ERROR, "pjsip", status, "Error connecting conference!");
        signalLogData(info);
        return false;
    }

    return true;
}
示例#11
0
/*****************************************************************************
 * test: play WAV file
 */
static void systest_play_wav(unsigned path_cnt, const char *paths[])
{
    pjsua_player_id play_id = PJSUA_INVALID_ID;
    enum gui_key key;
    test_item_t *ti;
    const char *title = "WAV File Playback Test";
    pj_status_t status;

    ti = systest_alloc_test_item(title);
    if (!ti)
	return;

    pj_ansi_snprintf(textbuf, sizeof(textbuf),
		     "This test will play %s file to "
		     "the speaker. Please listen carefully for audio "
		     "impairments such as stutter. Let this test run "
		     "for a while to make sure that everything is okay."
		     " Press OK to start, CANCEL to skip",
		     paths[0]);

    key = gui_msgbox(title, textbuf,
		     WITH_OKCANCEL);
    if (key != KEY_OK) {
	ti->skipped = PJ_TRUE;
	return;
    }

    PJ_LOG(3,(THIS_FILE, "Running %s", title));

    /* WAV port */
    status = create_player(path_cnt, paths, &play_id);
    if (status != PJ_SUCCESS)
	goto on_return;

    status = pjsua_conf_connect(pjsua_player_get_conf_port(play_id), 0);
    if (status != PJ_SUCCESS)
	goto on_return;

    key = gui_msgbox(title,
		     "WAV file should be playing now in the "
		     "speaker. Press OK to stop. ", WITH_OK);

    status = PJ_SUCCESS;

on_return:
    if (play_id != -1)
	pjsua_player_destroy(play_id);

    if (status != PJ_SUCCESS) {
	systest_perror("Sorry we've encountered error", 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;
}
示例#12
0
void ringback_start(){
	if (app_config.ringback_on) {
		//Already ringing back
		return;
	}
	app_config.ringback_on = PJ_TRUE;
    if (++app_config.ringback_cnt==1 && app_config.ringback_slot!=PJSUA_INVALID_ID){
    	pjsua_conf_connect(app_config.ringback_slot, 0);
    }
}
示例#13
0
void ringback_start() {
	if (css_var.ringback_on) {
		//Already ringing back
		return;
	}
	css_var.ringback_on = PJ_TRUE;
	if (++css_var.ringback_cnt == 1 && css_var.ringback_slot != PJSUA_INVALID_ID) {
		pjsua_conf_connect(css_var.ringback_slot, 0);
	}
}
示例#14
0
void SipAccount::onCallMediaState(pjsua_call_id call_id) {
  Logger::debug("SipAccount::onCallMediaState(call_id=%d)...", call_id);

  pjsua_call_info ci;
  pjsua_call_get_info(call_id, &ci);

  if (ci.media_status == PJSUA_CALL_MEDIA_ACTIVE) {
    // connect active call to silence
    pjsua_conf_connect(m_pPhone->getMediaConfSilenceId(), ci.conf_slot);
  }
}
示例#15
0
void QVDoorcom::onIncomingCall(int call_id) {
    pj_status_t status;

    if (active_call >= 0) {
        return;
    }
    qDebug() << "incoming call" << call_id;
    active_call = call_id;
    w_dooropen->hide();
    popup->show();
#ifdef DOORBELL_WAV
    status = pjmedia_wav_player_port_set_pos(bell_file_port,0);
    qDebug() << "Rewind status" << status;
    if (status == PJ_SUCCESS) {
        pjsua_conf_connect(bell_port_id,0);
//        pjsua_conf_adjust_tx_level(0,1.0);
    }
#else
    pjsua_conf_connect(bell_port_id,0);
#endif
}
示例#16
0
void MainWin::on_call_media_state(pjsua_call_id call_id)
{
    pjsua_call_info ci;

    pjsua_call_get_info(call_id, &ci);

    for (unsigned i=0; i<ci.media_cnt; ++i) {
	if (ci.media[i].type == PJMEDIA_TYPE_AUDIO) {
	    switch (ci.media[i].status) {
	    case PJSUA_CALL_MEDIA_ACTIVE:
		pjsua_conf_connect(ci.media[i].stream.aud.conf_slot, 0);
		pjsua_conf_connect(0, ci.media[i].stream.aud.conf_slot);
		break;
	    default:
		break;
	    }
	} else if (ci.media[i].type == PJMEDIA_TYPE_VIDEO) {
	    emit signalInitVideoWindow();
	}
    }
}
示例#17
0
void BlabbleCall::OnCallMediaState()
{
	if (call_id_ == INVALID_CALL)
		return;

	pjsua_call_info info;
	pj_status_t status;
	if ((status = pjsua_call_get_info(call_id_, &info)) != PJ_SUCCESS) {
		BLABBLE_LOG_ERROR("Unable to get call info. PJSIP call id: " << call_id_ << ", global id: " << id_ << ", pjsua_call_get_info returned " << status);
		StopRinging();
		return;
	}

	if (info.media_status == PJSUA_CALL_MEDIA_ACTIVE) 
	{
		StopRinging();

		// When media is active, connect call to sound device.
		pjsua_conf_connect(info.conf_slot, 0);
		pjsua_conf_connect(0, info.conf_slot);
	}
}
示例#18
0
static void on_call_media_state(pjsua_call_id call_id) {
	ics_t *data;
	pjsua_call_info ci;

	pjsua_call_get_info(call_id, &ci);

	//! Khoi tao mot connect media flow tu app nay sang app khac
	if (ci.media_status == PJSUA_CALL_MEDIA_ACTIVE) {
		pjsua_conf_connect(ci.conf_slot, 0); // ntt1->quy
		pjsua_conf_connect(0, ci.conf_slot); // quy->ntt1
	}

	pjsua_call_get_info(call_id, &ci);
	data = (ics_t *)pjsua_acc_get_user_data(ci.acc_id);
	opool_item_t *p_item = opool_get(&data->opool);
	build_call_media_state_event((ics_event_t *)p_item->data, call_id, ci.media_status);	
	ics_event_t *event = (ics_event_t *)p_item->data;

	//	queue_enqueue(&data->queue, (void *)p_item);
	process_event(event);

}
示例#19
0
文件: ics.c 项目: mocidis/ics
static void _ics_conference_call(ics_t *data, int call_id) {
    int i, max;
    PJ_UNUSED_ARG(data);

    max = pjsua_call_get_count();
    SHOW_LOG(3, "Let's conference call!\n");
    pjsua_call_info ci;

#if 1
    if ( (call_id != current_call) && pjsua_call_is_active(call_id)  ) {
        pjsua_call_reinvite(call_id, PJ_TRUE, NULL);
        for (i = 0; i < max; i++) {
            if (pjsua_call_has_media(i) != 0) {
                pjsua_conf_connect(pjsua_call_get_conf_port(call_id), pjsua_call_get_conf_port(i));		
                pjsua_conf_connect(pjsua_call_get_conf_port(i), pjsua_call_get_conf_port(call_id));
            }
        }
    }
    else
        SHOW_LOG(3, "Cannot transfer call!\n");
#endif

    //For test only:
#if 1


    for (i = 0; i < max; i++){	
        if (pjsua_call_is_active(i) && (i != current_call)) {
            pjsua_call_reinvite(i, PJ_TRUE, NULL);
            pjsua_call_get_info(i, &ci);
            pjsua_conf_connect(pjsua_call_get_conf_port(ci.id), pjsua_call_get_conf_port(current_call));		
            pjsua_conf_connect(pjsua_call_get_conf_port(current_call), pjsua_call_get_conf_port(ci.id));
        }
        break;
    }
#endif

}
示例#20
0
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();
        }
    }
}
示例#21
0
// helper for creating call-recorder
static void create_recorder(pjsua_call_info ci)
{
	// specify target file
	pj_str_t rec_file = pj_str(app_cfg.record_file);
	pj_status_t status = PJ_ENOTFOUND;
	
	log_message("Creating recorder ... ");
	
	// Create recorder for call
	status = pjsua_recorder_create(&rec_file, 0, NULL, 0, 0, &rec_id);
	if (status != PJ_SUCCESS) error_exit("Error recording answer", status);
	
	// connect active call to call recorder
	pjsua_conf_port_id rec_port = pjsua_recorder_get_conf_port(rec_id);		
	pjsua_conf_connect(ci.conf_slot, rec_port);
	
	log_message("Done.\n");
}
示例#22
0
/*****************************************************************************
 * 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;
}
示例#23
0
int dll_playWav(char* wavFile, int callId)
{
       pj_status_t status;

       /* Infos Player */
       pjsua_player_id player_id;            // Ident. for the player
       pjmedia_port *media_port;           // Struct. media_port
       pjsua_conf_port_id conf_port;       // Conference port for the player
 
       /* Infos Call Session */
       pjsua_call_info call_info;

       /********************************************
       / 1- Check if Call exists and is active
       ********************************************/

       // Get call_info from callId
       pjsua_call_get_info(callId, &call_info);

       if (call_info.media_status != PJSUA_CALL_MEDIA_ACTIVE)
               return -1;

       /********************************************
       / 2- Load the WAV File - Create the player
       ********************************************/
       status = pjsua_player_create(&pj_str(wavFile), PJMEDIA_FILE_NO_LOOP, &player_id);

       /********************************************
       / 3- Register the Callback C++ Function "on_wavplayerEof_callback"
       ********************************************/

       if (status == PJ_SUCCESS)
       {
               // Get media_port from player_id
               status = pjsua_player_get_port(player_id, &media_port);
       }
 
       if (status == PJ_SUCCESS)
       {
               // Prepare argument for Callback
               wavplayerEof_Data* args = (wavplayerEof_Data*)malloc(sizeof(wavplayerEof_Data));
               args->playerId = player_id;
               args->callId = callId;     

               // Register the Callback, launched when the End of the Wave File is reached
               status = pjmedia_wav_player_set_eof_cb(media_port, args, &on_wavplayerEof_callback);
       }
 
       /********************************************
       / 4- Stream the file to the Call Session
       ********************************************/

       // Get conf_port from player_id
       if (status == PJ_SUCCESS)
               conf_port = pjsua_player_get_conf_port(player_id);

 
       // one way connect conf_port (wav player) to call_info.conf_slot (call)
       if ((status == PJ_SUCCESS)&&(conf_port != PJSUA_INVALID_ID)&&(call_info.conf_slot != 0))        // test if conf_port valid, and if conf_slot != soundcard
       {
               status = pjsua_conf_connect(conf_port, call_info.conf_slot);
       }

       PJ_LOG(3,(THIS_FILE,"Wav Play, status %d",status));

       if (status != PJ_SUCCESS)
               return -1;

       return player_id;
}
示例#24
0
/*
* Callback on media state changed event.
* The action may connect the call to sound device, to file, or
* to loop the call.
*/
static void on_call_media_state(pjsua_call_id call_id)
{
    pjsua_call_info call_info;

    pjsua_call_get_info(call_id, &call_info);

    /* Connect ports appropriately when media status is ACTIVE or REMOTE HOLD,
     * otherwise we should NOT connect the ports.
     */
    if (call_info.media_status == PJSUA_CALL_MEDIA_ACTIVE ||
	call_info.media_status == PJSUA_CALL_MEDIA_REMOTE_HOLD)
    {
	pj_bool_t connect_sound = PJ_TRUE;

	/* Loopback sound, if desired */
	if (app_config.auto_loop) {
	    pjsua_conf_connect(call_info.conf_slot, call_info.conf_slot);
	    connect_sound = PJ_FALSE;
	}

	    /* Automatically record conversation, if desired */
	    if (app_config.auto_rec && app_config.rec_port != PJSUA_INVALID_ID) {
		pjsua_conf_connect(call_info.conf_slot, app_config.rec_port);
	    }

	/* Stream a file, if desired */
	if ((app_config.auto_play || app_config.auto_play_hangup) && 
	    app_config.wav_port != PJSUA_INVALID_ID)
	{
	    pjsua_conf_connect(app_config.wav_port, call_info.conf_slot);
	    connect_sound = PJ_FALSE;
	}

	/* Put call in conference with other calls, if desired */
	if (app_config.auto_conf) {
	    pjsua_call_id call_ids[PJSUA_MAX_CALLS];
	    unsigned call_cnt=PJ_ARRAY_SIZE(call_ids);
	    unsigned i;

	    /* Get all calls, and establish media connection between
	     * this call and other calls.
	     */
	    pjsua_enum_calls(call_ids, &call_cnt);

	    for (i=0; i<call_cnt; ++i) {
		if (call_ids[i] == call_id)
		    continue;
		
		if (!pjsua_call_has_media(call_ids[i]))
		    continue;

		pjsua_conf_connect(call_info.conf_slot,
				   pjsua_call_get_conf_port(call_ids[i]));
		pjsua_conf_connect(pjsua_call_get_conf_port(call_ids[i]),
				   call_info.conf_slot);

		/* Automatically record conversation, if desired */
		if (app_config.auto_rec && app_config.rec_port != PJSUA_INVALID_ID) {
		    pjsua_conf_connect(pjsua_call_get_conf_port(call_ids[i]), 
				       app_config.rec_port);
		}

	    }

	    /* Also connect call to local sound device */
	    connect_sound = PJ_TRUE;
	}

	/* Otherwise connect to sound device */
	if (connect_sound) {
	    pjsua_conf_connect(call_info.conf_slot, 0);
	    pjsua_conf_connect(0, call_info.conf_slot);

	    /* Automatically record conversation, if desired */
	    if (app_config.auto_rec && app_config.rec_port != PJSUA_INVALID_ID) {
		pjsua_conf_connect(call_info.conf_slot, app_config.rec_port);
		pjsua_conf_connect(0, app_config.rec_port);
	    }
	}
    }

	PJ_LOG(3,(THIS_FILE, "Media for call %d is active", call_id));

    /* Handle media status */
    switch (call_info.media_status) {
    case PJSUA_CALL_MEDIA_ACTIVE:
	PJ_LOG(3,(THIS_FILE, "Media for call %d is active", call_id));
	break;

    case PJSUA_CALL_MEDIA_LOCAL_HOLD:
	PJ_LOG(3,(THIS_FILE, "Media for call %d is suspended (hold) by local",
		  call_id));
  // call on call hold handler
  cb_callholdconf(call_id);
	break;

    case PJSUA_CALL_MEDIA_REMOTE_HOLD:
	PJ_LOG(3,(THIS_FILE, 
		  "Media for call %d is suspended (hold) by remote",
		  call_id));
	break;

    case PJSUA_CALL_MEDIA_ERROR:
	PJ_LOG(3,(THIS_FILE,
		  "Media has reported error, disconnecting call"));
	{
	    pj_str_t reason = pj_str("ICE negotiation failed");
	pjsua_call_hangup(call_id, 500, &reason, NULL);
	}
	break;

    case PJSUA_CALL_MEDIA_NONE:
	PJ_LOG(3,(THIS_FILE, 
		  "Media for call %d is inactive",
		  call_id));
	break;

    default:
	pj_assert(!"Unhandled media status");
	break;
    }
}
示例#25
0
static void systest_aec_test(void)
{
    const char *ref_wav_paths[] = { add_path(res_path, WAV_PLAYBACK_PATH),
				    ALT_PATH1 WAV_PLAYBACK_PATH };
    pjsua_player_id player_id = PJSUA_INVALID_ID;
    pjsua_recorder_id writer_id = PJSUA_INVALID_ID;
    enum gui_key key;
    test_item_t *ti;
    const char *title = "AEC/AES Test";
    unsigned last_ec_tail = 0;
    pj_status_t status;
    pj_str_t tmp;

    ti = systest_alloc_test_item(title);
    if (!ti)
	return;

    key = gui_msgbox(title,
		     "This test will try to find whether the AEC/AES "
		     "works good on this system. Test will play a file "
		     "while recording from mic. The recording will be "
		     "played back later so you can check if echo is there. "
		     "Press OK to start.",
		     WITH_OKCANCEL);
    if (key != KEY_OK) {
	ti->skipped = PJ_TRUE;
	return;
    }

    /* Save current EC tail */
    status = pjsua_get_ec_tail(&last_ec_tail);
    if (status != PJ_SUCCESS)
	goto on_return;

    /* Set EC tail setting to default */
    status = pjsua_set_ec(PJSUA_DEFAULT_EC_TAIL_LEN, 0);
    if (status != PJ_SUCCESS)
	goto on_return;

    /*
     * Create player and recorder
     */
    status = create_player(PJ_ARRAY_SIZE(ref_wav_paths), ref_wav_paths,
			   &player_id);
    if (status != PJ_SUCCESS) {
	PJ_PERROR(1,(THIS_FILE, status, "Error opening WAV file %s",
		     WAV_PLAYBACK_PATH));
	goto on_return;
    }

    status = pjsua_recorder_create(
                 pj_cstr(&tmp, add_path(doc_path, AEC_REC_PATH)), 0, 0, -1,
                 0, &writer_id);
    if (status != PJ_SUCCESS) {
	PJ_PERROR(1,(THIS_FILE, status, "Error writing WAV file %s",
		     AEC_REC_PATH));
	goto on_return;
    }

    /*
     * Start playback and recording.
     */
    pjsua_conf_connect(pjsua_player_get_conf_port(player_id), 0);
    pj_thread_sleep(100);
    pjsua_conf_connect(0, pjsua_recorder_get_conf_port(writer_id));

    /* Wait user signal */
    gui_msgbox(title, "AEC/AES test is running. Press OK to stop this test.",
	       WITH_OK);

    /*
     * Stop and close playback and recorder
     */
    pjsua_conf_disconnect(0, pjsua_recorder_get_conf_port(writer_id));
    pjsua_conf_disconnect(pjsua_player_get_conf_port(player_id), 0);
    pjsua_recorder_destroy(writer_id);
    pjsua_player_destroy(player_id);
    player_id = PJSUA_INVALID_ID;
    writer_id = PJSUA_INVALID_ID;

    /*
     * Play the result.
     */
    status = pjsua_player_create(
                 pj_cstr(&tmp, add_path(doc_path, AEC_REC_PATH)),
                 0, &player_id);
    if (status != PJ_SUCCESS) {
	PJ_PERROR(1,(THIS_FILE, status, "Error opening WAV file %s", AEC_REC_PATH));
	goto on_return;
    }
    pjsua_conf_connect(pjsua_player_get_conf_port(player_id), 0);

    /* Wait user signal */
    gui_msgbox(title, "We are now playing the captured audio from the mic. "
		      "Check if echo (of the audio played back previously) is "
		      "present in the audio. The recording is stored in "
		      AEC_REC_PATH " for offline analysis. "
		      "Press OK to stop.",
		      WITH_OK);

    pjsua_conf_disconnect(pjsua_player_get_conf_port(player_id), 0);

    key = gui_msgbox(title,
		     "Did you notice any echo in the recording?",
		     WITH_YESNO);


on_return:
    if (player_id != PJSUA_INVALID_ID)
	pjsua_player_destroy(player_id);
    if (writer_id != PJSUA_INVALID_ID)
	pjsua_recorder_destroy(writer_id);

    /* Wait until sound device closed before restoring back EC tail setting */
    while (pjsua_snd_is_active())
	pj_thread_sleep(10);
    pjsua_set_ec(last_ec_tail, 0);


    if (status != PJ_SUCCESS) {
	systest_perror("Sorry we encountered an error: ", status);
	ti->success = PJ_FALSE;
	pj_strerror(status, ti->reason, sizeof(ti->reason));
    } else if (key == KEY_YES) {
	ti->success = PJ_FALSE;
	if (!ti->success) {
	    pj_ansi_strcpy(ti->reason, USER_ERROR);
	}
    } else {
	char msg[200];

	pj_ansi_snprintf(msg, sizeof(msg), "Test succeeded.\r\n");

	ti->success = PJ_TRUE;
	pj_ansi_strncpy(ti->reason, msg, sizeof(ti->reason));
	ti->reason[sizeof(ti->reason)-1] = '\0';
    }
}
示例#26
0
static void systest_latency_test(void)
{
    const char *ref_wav_paths[] = { add_path(res_path, WAV_TOCK8_PATH), ALT_PATH1 WAV_TOCK8_PATH };
    pj_str_t rec_wav_file;
    pjsua_player_id play_id = PJSUA_INVALID_ID;
    pjsua_conf_port_id play_slot = PJSUA_INVALID_ID;
    pjsua_recorder_id rec_id = PJSUA_INVALID_ID;
    pjsua_conf_port_id rec_slot = PJSUA_INVALID_ID;
    pj_pool_t *pool = NULL;
    pjmedia_port *wav_port = NULL;
    unsigned lat_sum=0, lat_cnt=0, lat_min=0, lat_max=0;
    enum gui_key key;
    test_item_t *ti;
    const char *title = "Audio Latency Test";
    pj_status_t status;

    ti = systest_alloc_test_item(title);
    if (!ti)
	return;

    key = gui_msgbox(title,
		     "This test will try to find the audio device's "
		     "latency. We will play a special WAV file to the "
		     "speaker for ten seconds, then at the end "
		     "calculate the latency. Please don't do anything "
		     "until the test is done.", WITH_OKCANCEL);
    if (key != KEY_OK) {
	ti->skipped = PJ_TRUE;
	return;
    }
    key = gui_msgbox(title,
		     "For this test to work, we must be able to capture "
		     "the audio played in the speaker (the echo), and only"
		     " that audio (i.e. you must be in relatively quiet "
		     "place to run this test). "
		     "Press OK to start, or CANCEL to skip.",
		     WITH_OKCANCEL);
    if (key != KEY_OK) {
	ti->skipped = PJ_TRUE;
	return;
    }

    PJ_LOG(3,(THIS_FILE, "Running %s", title));

    status = create_player(PJ_ARRAY_SIZE(ref_wav_paths), ref_wav_paths,
			   &play_id);
    if (status != PJ_SUCCESS)
	goto on_return;

    play_slot = pjsua_player_get_conf_port(play_id);

    rec_wav_file = pj_str(add_path(doc_path, WAV_LATENCY_OUT_PATH));
    status = pjsua_recorder_create(&rec_wav_file, 0, NULL, -1, 0, &rec_id);
    if (status != PJ_SUCCESS)
	goto on_return;

    rec_slot = pjsua_recorder_get_conf_port(rec_id);

    /* Setup the test */
    //status = pjsua_conf_connect(0, 0);
    status = pjsua_conf_connect(play_slot, 0);
    status = pjsua_conf_connect(0, rec_slot);
    status = pjsua_conf_connect(play_slot, rec_slot);


    /* We're running */
    PJ_LOG(3,(THIS_FILE, "Please wait while test is running (~10 sec)"));
    gui_sleep(10);

    /* Done with the test */
    //status = pjsua_conf_disconnect(0, 0);
    status = pjsua_conf_disconnect(play_slot, rec_slot);
    status = pjsua_conf_disconnect(0, rec_slot);
    status = pjsua_conf_disconnect(play_slot, 0);

    pjsua_recorder_destroy(rec_id);
    rec_id = PJSUA_INVALID_ID;

    pjsua_player_destroy(play_id);
    play_id = PJSUA_INVALID_ID;

    /* Confirm that echo is heard */
    gui_msgbox(title,
	       "Test is done. Now we need to confirm that we indeed "
	       "captured the echo. We will play the captured audio "
	       "and please confirm that you can hear the 'tock' echo.",
	       WITH_OK);

    status = pjsua_player_create(&rec_wav_file, 0, &play_id);
    if (status != PJ_SUCCESS)
	goto on_return;

    play_slot = pjsua_player_get_conf_port(play_id);

    status = pjsua_conf_connect(play_slot, 0);
    if (status != PJ_SUCCESS)
	goto on_return;

    key = gui_msgbox(title,
		     "The captured audio is being played back now. "
		     "Can you hear the 'tock' echo?",
		     WITH_YESNO);

    pjsua_player_destroy(play_id);
    play_id = PJSUA_INVALID_ID;

    if (key != KEY_YES)
	goto on_return;

    /* Now analyze the latency */
    pool = pjsua_pool_create("latency", 512, 512);

    status = pjmedia_wav_player_port_create(pool, rec_wav_file.ptr, 0, 0, 0, &wav_port);
    if (status != PJ_SUCCESS)
	goto on_return;

    status = calculate_latency(pool, wav_port, &lat_sum, &lat_cnt,
			       &lat_min, &lat_max);
    if (status != PJ_SUCCESS)
	goto on_return;

on_return:
    if (wav_port)
	pjmedia_port_destroy(wav_port);
    if (pool)
	pj_pool_release(pool);
    if (play_id != PJSUA_INVALID_ID)
	pjsua_player_destroy(play_id);
    if (rec_id != PJSUA_INVALID_ID)
	pjsua_recorder_destroy(rec_id);

    if (status != PJ_SUCCESS) {
	systest_perror("Sorry we encountered an error: ", status);
	ti->success = PJ_FALSE;
	pj_strerror(status, ti->reason, sizeof(ti->reason));
    } else if (key != KEY_YES) {
	ti->success = PJ_FALSE;
	if (!ti->success) {
	    pj_ansi_strcpy(ti->reason, USER_ERROR);
	}
    } else {
	char msg[200];
	pj_size_t msglen;

	pj_ansi_snprintf(msg, sizeof(msg),
			 "The sound device latency:\r\n"
			 " Min=%u, Max=%u, Avg=%u\r\n",
			 lat_min, lat_max, lat_sum/lat_cnt);
	msglen = strlen(msg);

	if (lat_sum/lat_cnt > 500) {
	    pj_ansi_snprintf(msg+msglen, sizeof(msg)-msglen,
			     "The latency is huge!\r\n");
	    msglen = strlen(msg);
	} else if (lat_sum/lat_cnt > 200) {
	    pj_ansi_snprintf(msg+msglen, sizeof(msg)-msglen,
			     "The latency is quite high\r\n");
	    msglen = strlen(msg);
	}

	key = gui_msgbox(title, msg, WITH_OK);

	ti->success = PJ_TRUE;
	pj_ansi_strncpy(ti->reason, msg, sizeof(ti->reason));
	ti->reason[sizeof(ti->reason)-1] = '\0';
    }
}
示例#27
0
/*****************************************************************************
 * test: record audio
 */
static void systest_rec_audio(void)
{
    const pj_str_t filename = pj_str(add_path(doc_path, WAV_REC_OUT_PATH));
    pj_pool_t *pool = NULL;
    enum gui_key key;
    pjsua_recorder_id rec_id = PJSUA_INVALID_ID;
    pjsua_player_id play_id = PJSUA_INVALID_ID;
    pjsua_conf_port_id rec_slot = PJSUA_INVALID_ID;
    pjsua_conf_port_id play_slot = PJSUA_INVALID_ID;
    pj_status_t status = PJ_SUCCESS;
    const char *title = "Audio Recording";
    test_item_t *ti;

    ti = systest_alloc_test_item(title);
    if (!ti)
	return;

    key = gui_msgbox(title,
		     "This test will allow you to record audio "
		     "from the microphone, and playback the "
		     "audio to the speaker. Press OK to start recording, "
		     "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("rectest", 512, 512);

    status = pjsua_recorder_create(&filename, 0, NULL, -1, 0, &rec_id);
    if (status != PJ_SUCCESS)
	goto on_return;

    rec_slot = pjsua_recorder_get_conf_port(rec_id);

    status = pjsua_conf_connect(0, rec_slot);
    if (status != PJ_SUCCESS)
	goto on_return;

    key = gui_msgbox(title,
		     "Recording is in progress now, please say "
		     "something in the microphone. Press OK "
		     "to stop recording", WITH_OK);

    pjsua_conf_disconnect(0, rec_slot);
    rec_slot = PJSUA_INVALID_ID;
    pjsua_recorder_destroy(rec_id);
    rec_id = PJSUA_INVALID_ID;

    status = pjsua_player_create(&filename, 0, &play_id);
    if (status != PJ_SUCCESS)
	goto on_return;

    play_slot = pjsua_player_get_conf_port(play_id);

    status = pjsua_conf_connect(play_slot, 0);
    if (status != PJ_SUCCESS)
	goto on_return;

    key = gui_msgbox(title,
		     "Recording has been stopped. "
		     "The recorded audio is being played now to "
		     "the speaker device, in a loop. Listen for "
		     "any audio impairments. Press OK to stop.",
		     WITH_OK);

on_return:
    if (rec_slot != PJSUA_INVALID_ID)
	pjsua_conf_disconnect(0, rec_slot);
    if (rec_id != PJSUA_INVALID_ID)
	pjsua_recorder_destroy(rec_id);
    if (play_slot != PJSUA_INVALID_ID)
	pjsua_conf_disconnect(play_slot, 0);
    if (play_id != PJSUA_INVALID_ID)
	pjsua_player_destroy(play_id);
    if (pool)
	pj_pool_release(pool);

    if (status != PJ_SUCCESS) {
	systest_perror("Sorry we encountered an error: ", 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_snprintf(textbuf, sizeof(textbuf),
			     "You will probably need to copy the recorded "
			     "WAV file %s to a desktop computer and analyze "
			     "it, to find out whether it's a recording "
			     "or playback problem.",
			     WAV_REC_OUT_PATH);
	    gui_msgbox(title, textbuf, WITH_OK);
	    pj_ansi_strcpy(ti->reason, USER_ERROR);
	}
    }
}