static THREADFUNCDECL(main_proc_thread_func) { const int sleep_ms = 5; const int counts_per_second = 1000 / sleep_ms; static int refresh_registration_count = 0; static int audio_error_count = 0; static int audio_error_state = 0; THREADFUNCRET(ret); /* Increase Priority */ iaxci_prioboostbegin(); while ( !main_proc_thread_flag ) { get_iaxc_lock(); service_network(); if ( !test_mode && (!audio_error_state || audio_error_count++ % counts_per_second == 0) ) { /* There are cases when service audio fails such * as when there is no audio devices present in * the system. In these cases, only call * service_audio() once per second until it * succeeds. */ if ( (audio_error_state = service_audio()) ) { iaxci_usermsg(IAXC_NOTICE, "failed to service audio"); if ( audio_error_count / counts_per_second == 5 ) iaxci_usermsg(IAXC_TEXT_TYPE_FATALERROR, "cannot open audio device" " after several tries"); } } // Check registration refresh once a second if ( refresh_registration_count++ > counts_per_second ) { iaxc_refresh_registrations(); refresh_registration_count = 0; } put_iaxc_lock(); iaxc_millisleep(sleep_ms); } /* Decrease priority */ iaxci_prioboostend(); main_proc_thread_flag = -1; return ret; }
EXPORT void iaxc_dump_all_calls(void) { int callNo; get_iaxc_lock(); for ( callNo = 0; callNo < max_calls; callNo++ ) iaxc_dump_one_call(callNo); put_iaxc_lock(); }
EXPORT int iaxc_unregister( int id ) { int count = 0; get_iaxc_lock(); count = iaxc_remove_registration_by_id(id); put_iaxc_lock(); return count; }
EXPORT void iaxc_dump_call_number( int callNo ) { if ( ( callNo >= 0 ) && ( callNo < max_calls ) ) { get_iaxc_lock(); 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_send_url(const 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(); } }
EXPORT void iaxc_send_text_call(int callNo, const char * text) { if ( callNo < 0 || !(calls[callNo].state & IAXC_CALL_STATE_ACTIVE) ) return; get_iaxc_lock(); if ( calls[callNo].state & IAXC_CALL_STATE_ACTIVE ) iax_send_text(calls[callNo].session, text); put_iaxc_lock(); }
EXPORT void iaxc_send_text(const 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_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_reject_call_number( int callNo ) { if ( ( callNo >= 0 ) && ( callNo < max_calls ) ) { get_iaxc_lock(); iax_reject(calls[callNo].session, "Call rejected manually."); iaxc_clear_call(callNo); put_iaxc_lock(); } }
EXPORT void iaxc_send_text_call(int callNo, const char * text) { if ( callNo >= 0 && callNo < max_calls ) { get_iaxc_lock(); if ( calls[callNo].state & IAXC_CALL_STATE_ACTIVE ) iax_send_text(calls[callNo].session, text); put_iaxc_lock(); } }
EXPORT int iaxc_audio_devices_set(int input, int output, int ring) { int ret; if ( test_mode ) return 0; get_iaxc_lock(); ret = audio_driver.select_devices(&audio_driver, input, output, ring); put_iaxc_lock(); return ret; }
EXPORT int iaxc_stop_sound(int id) { int ret; if ( test_mode ) return 0; get_iaxc_lock(); ret = audio_driver.stop_sound(id); put_iaxc_lock(); return ret; }
EXPORT int iaxc_play_sound(struct iaxc_sound *s, int ring) { int ret; if ( test_mode ) return 0; get_iaxc_lock(); ret = audio_driver.play_sound(s,ring); put_iaxc_lock(); return ret; }
EXPORT void iaxc_shutdown() { iaxc_dump_all_calls(); get_iaxc_lock(); if ( !test_mode ) { audio_driver.destroy(&audio_driver); audio_destroy(); #ifdef USE_VIDEO video_destroy(); #endif } /* destroy enocders and decoders for all existing calls */ if ( calls ) { int i; for ( i=0 ; i<max_calls ; i++ ) { if ( calls[i].encoder ) calls[i].encoder->destroy(calls[i].encoder); if ( calls[i].decoder ) calls[i].decoder->destroy(calls[i].decoder); if ( calls[i].vencoder ) calls[i].vencoder->destroy(calls[i].vencoder); if ( calls[i].vdecoder ) calls[i].vdecoder->destroy(calls[i].vdecoder); } free(calls); calls = NULL; } put_iaxc_lock(); #ifdef WIN32 closesocket(iax_get_fd()); //fd: #endif free(calls); MUTEXDESTROY(&event_queue_lock); MUTEXDESTROY(&iaxc_lock); }
EXPORT int iaxc_register_ex(const char * user, const char * pass, const char * host, int refresh) { struct iaxc_registration *newreg; newreg = (struct iaxc_registration *)malloc(sizeof (struct iaxc_registration)); if ( !newreg ) { iaxci_usermsg(IAXC_ERROR, "Can't make new registration"); return -1; } get_iaxc_lock(); newreg->session = iax_session_new(); if ( !newreg->session ) { iaxci_usermsg(IAXC_ERROR, "Can't make new registration session"); put_iaxc_lock(); return -1; } newreg->last = iax_tvnow(); newreg->refresh = refresh; strncpy(newreg->host, host, 256); strncpy(newreg->user, user, 256); strncpy(newreg->pass, pass, 256); /* send out the initial registration with refresh seconds */ iax_register(newreg->session, host, user, pass, refresh); /* add it to the list; */ newreg->id = ++next_registration_id; newreg->next = registrations; registrations = newreg; put_iaxc_lock(); return newreg->id; }
static THREADFUNCDECL(main_proc_thread_func) { static int refresh_registration_count = 0; THREADFUNCRET(ret); /* Increase Priority */ iaxci_prioboostbegin(); while ( !main_proc_thread_flag ) { get_iaxc_lock(); service_network(); if ( !test_mode ) service_audio(); // Check registration refresh once a second if ( refresh_registration_count++ > 1000/LOOP_SLEEP ) { iaxc_refresh_registrations(); refresh_registration_count = 0; } put_iaxc_lock(); iaxc_millisleep(LOOP_SLEEP); } /* Decrease priority */ iaxci_prioboostend(); main_proc_thread_flag = -1; return ret; }
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; }
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; }