EXPORT int iaxc_call_ex(const char *num, const char* callerid_name, const char* callerid_number, int video) { int video_format_capability = 0; int video_format_preferred = 0; int callNo = -1; 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; } } if ( callNo < 0 ) { iaxci_usermsg(IAXC_STATUS, "No free call appearances"); goto iaxc_call_bail; } newsession = iax_session_new(); if ( !newsession ) { iaxci_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); } if ( callerid_number != NULL ) strncpy(calls[callNo].callerid_number, callerid_number, IAXC_EVENT_BUFSIZ); if ( callerid_name != NULL ) strncpy(calls[callNo].callerid_name, callerid_name, 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; #ifdef USE_VIDEO if ( video ) iaxc_video_format_get_cap(&video_format_preferred, &video_format_capability); #endif iaxci_usermsg(IAXC_NOTICE, "Originating an %s call", video_format_preferred ? "audio+video" : "audio only"); iax_call(calls[callNo].session, calls[callNo].callerid_number, calls[callNo].callerid_name, num, NULL, 0, audio_format_preferred | video_format_preferred, audio_format_capability | video_format_capability); // does state stuff also iaxc_select_call(callNo); iaxc_call_bail: put_iaxc_lock(); return callNo; }
static void iaxc_handle_connect(struct iax_event * e) { #ifdef USE_VIDEO int video_format_capability; int video_format_preferred; #endif int video_format = 0; int format = 0; int callno; callno = iaxc_first_free_call(); if ( callno < 0 ) { iaxci_usermsg(IAXC_STATUS, "%i \n Incoming Call, but no appearances", callno); // XXX Reject this call!, or just ignore? //iax_reject(e->session, "Too many calls, we're busy!"); iax_accept(e->session, audio_format_preferred & e->ies.capability); iax_busy(e->session); return; } /* 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"); return; } #ifdef USE_VIDEO iaxc_video_format_get_cap(&video_format_preferred, &video_format_capability); /* first, see if they even want video */ video_format = (e->ies.format & IAXC_VIDEO_FORMAT_MASK); if ( video_format ) { /* next, try _their_ preferred format */ video_format &= video_format_capability; if ( !video_format ) { /* then, try our preferred format */ video_format = video_format_preferred & (e->ies.capability & IAXC_VIDEO_FORMAT_MASK); } if ( !video_format ) { /* finally, see if we have one in common */ video_format = video_format_capability & (e->ies.capability & IAXC_VIDEO_FORMAT_MASK); /* now choose amongst these, if we got one */ if ( video_format ) { video_format = iaxc_choose_codec(video_format); } } /* All video negotiations failed, then warn */ if ( !video_format ) { iaxci_usermsg(IAXC_NOTICE, "Notice: could not negotiate common video codec"); iaxci_usermsg(IAXC_NOTICE, "Notice: switching to audio-only call"); } } #endif /* USE_VIDEO */ calls[callno].vformat = video_format; 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); iaxci_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 | video_format); iax_ring_announce(calls[callno].session); iaxci_do_state_callback(callno); iaxci_usermsg(IAXC_STATUS, "Incoming call on line %d", callno); }
EXPORT int iaxc_call_ex(const char *num, const char* callerid_name, const char* callerid_number, int video) { int video_format_capability = 0; int video_format_preferred = 0; int callNo = -1; 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; } } if ( callNo < 0 ) { iaxci_usermsg(IAXC_STATUS, "No free call appearances"); goto iaxc_call_bail; } newsession = iax_session_new(); if ( !newsession ) { iaxci_usermsg(IAXC_ERROR, "Can't make new session"); goto iaxc_call_bail; } calls[callNo].session = newsession; codec_destroy( callNo ); /* When the ACCEPT comes back from the other-end, these formats * are set. Whether the format is set or not determines whether * we are in the Linked state (see the iax2 rfc). * These will have already been cleared by iaxc_clear_call(), * but we reset them anyway just to be pedantic. */ calls[callNo].format = 0; calls[callNo].vformat = 0; 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); } if ( callerid_number != NULL ) strncpy(calls[callNo].callerid_number, callerid_number, IAXC_EVENT_BUFSIZ); if ( callerid_name != NULL ) strncpy(calls[callNo].callerid_name, callerid_name, 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_OUTGOING; /* reset activity and ping "timers" */ iaxc_note_activity(callNo); calls[callNo].last_ping = calls[callNo].last_activity; #ifdef USE_VIDEO if ( video ) iaxc_video_format_get_cap(&video_format_preferred, &video_format_capability); #endif iaxci_usermsg(IAXC_NOTICE, "Originating an %s call", video_format_preferred ? "audio+video" : "audio only"); iax_call(calls[callNo].session, calls[callNo].callerid_number, calls[callNo].callerid_name, num, NULL, 0, audio_format_preferred | video_format_preferred, audio_format_capability | video_format_capability); // does state stuff also iaxc_select_call(callNo); iaxc_call_bail: put_iaxc_lock(); return callNo; }