⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 iaxclient_lib.c

📁 ppciaxclient softphone
💻 C
📖 第 1 页 / 共 3 页
字号:
	get_iaxc_lock();
	count = iaxc_remove_registration_by_id(id);
	put_iaxc_lock();
	return count;
}

EXPORT int iaxc_register(char *user, char *pass, char *host)
{
	struct iaxc_registration *newreg;

	newreg = malloc(sizeof (struct iaxc_registration));
	if(!newreg) {
		iaxc_usermsg(IAXC_ERROR, "Can't make new registration");
		return -1;
	}

	get_iaxc_lock();
	newreg->session = iax_session_new();
	if(!newreg->session) {
		iaxc_usermsg(IAXC_ERROR, "Can't make new registration session");
		put_iaxc_lock();
		return -1;
	}

	gettimeofday(&newreg->last,NULL);
	newreg->refresh = 120*1000*1000;  /* 120 seconds, in usecs */

	strncpy(newreg->host, host, 256);
	strncpy(newreg->user, user, 256);
	strncpy(newreg->pass, pass, 256);

	/* send out the initial registration timeout 300 seconds */
	iax_register(newreg->session, host, user, pass, 300);

	/* add it to the list; */
	newreg->id = ++next_registration_id;
	newreg->next = registrations;
	registrations = newreg;

	put_iaxc_lock();
	return newreg->id;
}

static void codec_destroy( int callNo )
{
	if( calls[callNo].encoder ) {
		calls[callNo].encoder->destroy( calls[callNo].encoder );
		calls[callNo].encoder = NULL;
	}
	if( calls[callNo].decoder ) {
		calls[callNo].decoder->destroy( calls[callNo].decoder );
		calls[callNo].decoder = NULL;
	}
}

EXPORT void iaxc_call(char *num)
{
	int callNo;
	struct iax_session *newsession;
	char *ext = strstr(num, "/");

	get_iaxc_lock();

        // if no call is selected, get a new appearance
        if(selected_call < 0) {
            callNo = iaxc_first_free_call();
        } else {
            // use selected call if not active, otherwise, get a new appearance
            if(calls[selected_call].state  & IAXC_CALL_STATE_ACTIVE) {
                callNo = iaxc_first_free_call();
            } else {
                 callNo = selected_call;
            }
        }

//	fprintf(stderr,"Trying to call");
	if(callNo < 0) {
		iaxc_usermsg(IAXC_STATUS, "No free call appearances");
		goto iaxc_call_bail;
	}

	newsession = iax_session_new();
	if(!newsession) {
		iaxc_usermsg(IAXC_ERROR, "Can't make new session");
		goto iaxc_call_bail;
	}

	calls[callNo].session = newsession;

	codec_destroy( callNo );

	if(ext) {
	    strncpy(calls[callNo].remote_name, num, IAXC_EVENT_BUFSIZ); 
    	    strncpy(calls[callNo].remote,    ++ext, IAXC_EVENT_BUFSIZ);
    	} else {
	    strncpy(calls[callNo].remote_name, num, IAXC_EVENT_BUFSIZ);
    	    strncpy(calls[callNo].remote,      "" , IAXC_EVENT_BUFSIZ);
     	}

 	strncpy(calls[callNo].local        , calls[callNo].callerid_name, IAXC_EVENT_BUFSIZ);
	strncpy(calls[callNo].local_context, "default", IAXC_EVENT_BUFSIZ);

	calls[callNo].state = IAXC_CALL_STATE_ACTIVE | IAXC_CALL_STATE_OUTGOING;

	/* reset activity and ping "timers" */
	iaxc_note_activity(callNo);
	calls[callNo].last_ping = calls[callNo].last_activity;

	iax_call(calls[callNo].session, calls[callNo].callerid_number,
	                                calls[callNo].callerid_name, num, NULL, 0,
					audio_format_preferred, audio_format_capability);

	// does state stuff also
	iaxc_select_call(callNo);

iaxc_call_bail:
	put_iaxc_lock();
}

EXPORT void iaxc_answer_call(int callNo) 
{
	if(callNo < 0)
	    return;
	    
	//fprintf(stderr, "iaxc answering call %d\n", callNo);
	calls[callNo].state |= IAXC_CALL_STATE_COMPLETE;
	calls[callNo].state &= ~IAXC_CALL_STATE_RINGING;
	iax_answer(calls[callNo].session);
	iaxc_do_state_callback(callNo);
}

EXPORT void iaxc_blind_transfer_call(int callNo, char *DestExtn)
{
	iax_transfer(calls[callNo].session, DestExtn);
}

static void iaxc_dump_one_call(int callNo)
{
      if(callNo < 0)
          return;
      if(calls[callNo].state == IAXC_CALL_STATE_FREE) return;
      
      iax_hangup(calls[callNo].session,"Dumped Call");
      iaxc_usermsg(IAXC_STATUS, "Hanging up call %d", callNo);
      iaxc_clear_call(callNo);
}

EXPORT void iaxc_dump_all_calls(void)
{
      int callNo;
      get_iaxc_lock();
	for(callNo=0; callNo<nCalls; callNo++)
	    iaxc_dump_one_call(callNo);
      put_iaxc_lock();
}


EXPORT void iaxc_dump_call(void)
{
    if(selected_call >= 0) {
	get_iaxc_lock();
	iaxc_dump_one_call(selected_call);
	put_iaxc_lock();
    }
}

EXPORT void iaxc_reject_call(void)
{
    if(selected_call >= 0) {
	iaxc_reject_call_number(selected_call);
    }
}

EXPORT void iaxc_reject_call_number( int callNo )
{
    if(callNo >= 0) {
	get_iaxc_lock();
	iax_reject(calls[callNo].session, "Call rejected manually.");
	iaxc_clear_call(callNo);
	put_iaxc_lock();
    }
}

EXPORT void iaxc_send_dtmf(char digit)
{
    if(selected_call >= 0) {
	get_iaxc_lock();
	if(calls[selected_call].state & IAXC_CALL_STATE_ACTIVE)
		iax_send_dtmf(calls[selected_call].session,digit);
	put_iaxc_lock();
    }
}

EXPORT void iaxc_send_text(char *text)
{
    if(selected_call >= 0) {
	get_iaxc_lock();
	if(calls[selected_call].state & IAXC_CALL_STATE_ACTIVE)
		iax_send_text(calls[selected_call].session, text);
	put_iaxc_lock();
    }
}

EXPORT void iaxc_send_url(char *url, int link)
{
    if(selected_call >= 0) {
	get_iaxc_lock();
	if(calls[selected_call].state & IAXC_CALL_STATE_ACTIVE)
		iax_send_url(calls[selected_call].session, url, link); 
	put_iaxc_lock();
    }
}

static int iaxc_find_call_by_session(struct iax_session *session)
{
	int i;
	for(i=0;i<nCalls;i++)
		if (calls[i].session == session)
			return i;
	return -1;
}

static struct iaxc_registration *iaxc_find_registration_by_session(struct iax_session *session) {
    struct iaxc_registration *reg;
    for (reg = registrations; reg != NULL; reg=reg->next)
        if (reg->session == session) break;
    return reg;
}

static void iaxc_handle_regreply(struct iax_event *e, struct iaxc_registration *reg) {

    iaxc_do_registration_callback(reg->id, e->etype, e->ies.msgcount);

    // XXX I think the session is no longer valid.. at least, that's
    // what miniphone does, and re-using the session doesn't seem to
    // work!
    iax_destroy(reg->session);
    reg->session = NULL;
    
    if (e->etype == IAX_EVENT_REGREJ) {
        // we were rejected, so end the registration
        iaxc_remove_registration_by_id(reg->id);
    }
}

/* this is what asterisk does */
static int iaxc_choose_codec(int formats) {
    int i;
    static int codecs[] = {
      IAXC_FORMAT_ULAW,
      IAXC_FORMAT_ALAW,
      IAXC_FORMAT_SLINEAR,
      IAXC_FORMAT_G726,
      IAXC_FORMAT_ADPCM,
      IAXC_FORMAT_GSM,
      IAXC_FORMAT_ILBC,
      IAXC_FORMAT_SPEEX,
      IAXC_FORMAT_LPC10,
      IAXC_FORMAT_G729A,
      IAXC_FORMAT_G723_1,
    };
    for(i=0;i<sizeof(codecs)/sizeof(int);i++)
	if(codecs[i] & formats)
	    return codecs[i];
    return 0;
}

static void iaxc_service_network() { 
	struct iax_event *e = 0;
	int callNo;
	struct iaxc_registration *reg;

	while ( (e = iax_get_event(0))) {
		// first, see if this is an event for one of our calls.
		callNo = iaxc_find_call_by_session(e->session);
		if(callNo >= 0) {
			iaxc_handle_network_event(e, callNo);
		} else if((reg = iaxc_find_registration_by_session(e->session)) != NULL) {
            iaxc_handle_regreply(e,reg);
        } else if((e->etype == IAX_EVENT_REGACK ) || (e->etype == IAX_EVENT_REGREJ )) { 
            iaxc_usermsg(IAXC_ERROR, "Unexpected registration reply");
		} else if(e->etype == IAX_EVENT_REGREQ ) {
			iaxc_usermsg(IAXC_ERROR, "Registration requested by someone, but we don't understand!");
		} else  if(e->etype == IAX_EVENT_CONNECT) {
			
			int format = 0;
			callNo = iaxc_first_free_call();

			if(callNo < 0) {
				iaxc_usermsg(IAXC_STATUS, "Incoming Call, but no appearances");
				// XXX Reject this call!, or just ignore?
				iax_reject(e->session, "Too many calls, we're busy!");
				goto bail;
			}

			/* negotiate codec */
			/* first, try _their_ preferred format */
			format = audio_format_capability & e->ies.format; 

			if(!format) {
			    /* then, try our preferred format */
			    format = audio_format_preferred & e->ies.capability; 
			}

			if(!format) {
			    /* finally, see if we have one in common */
			    format = audio_format_capability & e->ies.capability; 

			    /* now choose amongst these, if we got one */
			    if(format)
			    {
				format=iaxc_choose_codec(format);
			    }
			}
			
			if(!format) {
			    iax_reject(e->session, "Could not negotiate common codec");
				iaxc_usermsg(IAXC_STATUS,"Codec Negotiation Error");
			    goto bail;
			}

			calls[callNo].format = format;


			if(e->ies.called_number)
			    strncpy(calls[callNo].local,e->ies.called_number,
				IAXC_EVENT_BUFSIZ);
			else
			    strncpy(calls[callNo].local,"unknown",
				IAXC_EVENT_BUFSIZ);

			if(e->ies.called_context)
			    strncpy(calls[callNo].local_context,e->ies.called_context,
				IAXC_EVENT_BUFSIZ);
			else
			    strncpy(calls[callNo].local_context,"",
    				IAXC_EVENT_BUFSIZ);

			if(e->ies.calling_number)
			    strncpy(calls[callNo].remote,
  				e->ies.calling_number, IAXC_EVENT_BUFSIZ);
			else
			    strncpy(calls[callNo].remote,
    				"unknown", IAXC_EVENT_BUFSIZ);

			if(e->ies.calling_name)
			    strncpy(calls[callNo].remote_name,
    				e->ies.calling_name, IAXC_EVENT_BUFSIZ);
			else
			    strncpy(calls[callNo].remote_name,
    				"unknown", IAXC_EVENT_BUFSIZ);
			iaxc_note_activity(callNo);
			iaxc_usermsg(IAXC_STATUS, "Call from (%s)", calls[callNo].remote);

			codec_destroy( callNo );

			calls[callNo].session = e->session;
			calls[callNo].state = IAXC_CALL_STATE_ACTIVE|IAXC_CALL_STATE_RINGING;

			iax_accept(calls[callNo].session,format);
			iax_ring_announce(calls[callNo].session);

			iaxc_do_state_callback(callNo);

			iaxc_usermsg(IAXC_STATUS, "Incoming call on line %d", callNo);

		} else if (e->etype == IAX_EVENT_TIMEOUT) {
		    
			iaxc_usermsg(IAXC_STATUS, "Timeout for a non-existant session.  Dropping", e->etype);
			
		} else {
			iaxc_usermsg(IAXC_STATUS, "Event (type %d) for a non-existant session.  Dropping", e->etype);
		}
bail:
		iax_event_free(e);
	}
}

EXPORT int iaxc_audio_devices_get(struct iaxc_audio_device **devs, int *nDevs, int *input, int *output, int *ring) {
      *devs = audio.devices;
      *nDevs = audio.nDevices;
      audio.selected_devices(&audio,input,output,ring);
      return 0; 
}

EXPORT int iaxc_audio_devices_set(int input, int output, int ring) {
    int ret = 0;
    get_iaxc_lock();
    ret = audio.select_devices(&audio, input, output, ring);
    put_iaxc_lock();
    return ret;
}

EXPORT double iaxc_input_level_get() {
    return audio.input_level_get(&audio);
}

EXPORT double iaxc_output_level_get() {
    return audio.output_level_get(&audio);
}

EXPORT int iaxc_input_level_set(double level) {
    return audio.input_level_set(&audio, level);
}

EXPORT int iaxc_output_level_set(double level) {
    return audio.output_level_set(&audio, level);
}

EXPORT int iaxc_play_sound(struct iaxc_sound *s, int ring) {
    int ret = 0;
    get_iaxc_lock();
    ret = audio.play_sound(s,ring);
    put_iaxc_lock();
    return ret;
}

EXPORT int iaxc_stop_sound(int id) {
    int ret = 0;
    get_iaxc_lock();
    ret = audio.stop_sound(id);
    put_iaxc_lock();
    return ret;
}

EXPORT int iaxc_quelch(int callNo, int MOH)
{
	struct iax_session *session = calls[callNo].session;
	if (!session)
		return -1;

	return iax_quelch_moh(session, MOH);
}

EXPORT int iaxc_unquelch(int call)
{
	return iax_unquelch(calls[call].session);
}

EXPORT int iaxc_mic_boost_get( void )
{
	return audio.mic_boost_get( &audio ) ;
}

EXPORT int iaxc_mic_boost_set( int enable )
{
	return audio.mic_boost_set( &audio, enable ) ;
}

EXPORT char* iaxc_version(char* ver)
{
	strncpy(ver,   LIBVER,   IAXC_EVENT_BUFSIZ);
	return ver;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -