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; }
void do_iaxc_call (const char *username, const char *password, const char *voipserver, const char *number) { char dest[256]; snprintf (dest, sizeof (dest), "%s:%s@%s/%s", username, password, voipserver, number); iaxc_call (dest); iaxc_millisleep (DEFAULT_MILLISLEEP); }
static void service_network() { struct iax_event *e = 0; int callNo; struct iaxc_registration *reg; while ( (e = iax_get_event(0)) ) { #ifdef WIN32 iaxc_millisleep(0); //fd: #endif // first, see if this is an event for one of our calls. callNo = iaxc_find_call_by_session(e->session); if ( e->etype == IAX_EVENT_NULL ) { // Should we do something here? // Right now we do nothing, just go with the flow // and let the event be deallocated. } else 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 ) { iaxci_usermsg(IAXC_ERROR, "Unexpected registration reply"); } else if ( e->etype == IAX_EVENT_REGREQ ) { iaxci_usermsg(IAXC_ERROR, "Registration requested by someone, but we don't understand!"); } else if ( e->etype == IAX_EVENT_CONNECT ) { iaxc_handle_connect(e); } else if ( e->etype == IAX_EVENT_TIMEOUT ) { iaxci_usermsg(IAXC_STATUS, "Timeout for a non-existant session. Dropping", e->etype); } else { iaxci_usermsg(IAXC_STATUS, "Event (type %d) for a non-existant session. Dropping", e->etype); } iax_event_free(e); } }
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; }
void alarm_handler (int signal) { /* Check every DEFAULT_ALARM_TIMER seconds if position related things should happen */ if (check_special_frq (selected_frequency)) { strcpy (icao, "ZZZZ"); } else { strcpy (icao, icaobypos (airportlist, selected_frequency, data.LAT, data.LON, DEFAULT_RANGE)); } /* Check if we are out of range */ if (strlen (icao) == 0 && connected == 1) { /* Yes, we are out of range so hangup */ iaxc_dump_call (); iaxc_millisleep (5 * DEFAULT_MILLISLEEP); connected = 0; } /* Check if we are now in range */ else if (strlen (icao) != 0 && connected == 0) { icao2number (icao, selected_frequency, tmp); #ifdef DEBUG printf ("DEBUG: dialing %s %3.3f MHz: %s\n", icao, selected_frequency, tmp); #endif do_iaxc_call (username, password, voipserver, tmp); connected = 1; } }
static void handle_audio_event(struct iax_event *e, int callNo) { int total_consumed = 0; short fr[4096]; const int fr_samples = sizeof(fr) / sizeof(short); int samples, format; #ifdef WIN32 int cycles_max = 100; //fd: #endif struct iaxc_call *call; if ( callNo < 0 ) return; call = &calls[callNo]; if ( callNo != selected_call ) { /* drop audio for unselected call? */ return; } if ( audio_prefs & IAXC_AUDIO_PREF_RECV_DISABLE) { /* just drop silently incoming audio frames */ return; } samples = fr_samples; format = call->format & IAXC_AUDIO_FORMAT_MASK; do { int bytes_decoded; int mainbuf_delta = fr_samples - samples; bytes_decoded = audio_decode_audio(call, fr, e->data + total_consumed, e->datalen - total_consumed, format, &samples); if ( bytes_decoded < 0 ) { iaxci_usermsg(IAXC_STATUS, "Bad or incomplete voice packet. Unable to decode. dropping"); return; } /* Pass encoded audio back to the app if required */ if ( audio_prefs & IAXC_AUDIO_PREF_RECV_REMOTE_ENCODED ) iaxci_do_audio_callback(callNo, e->ts, IAXC_SOURCE_REMOTE, 1, format & IAXC_AUDIO_FORMAT_MASK, e->datalen - total_consumed, e->data + total_consumed); #ifdef WIN32 //fd: start: for some reason it loops here. Try to avoid it cycles_max--; if ( cycles_max < 0 ) { iaxc_millisleep(0); } //fd: end #endif total_consumed += bytes_decoded; if ( audio_prefs & IAXC_AUDIO_PREF_RECV_REMOTE_RAW ) { // audio_decode_audio returns the number of samples. // We are using 16 bit samples, so we need to double // the number to obtain the size in bytes. // format will also be 0 since this is raw audio int size = (fr_samples - samples - mainbuf_delta) * 2; iaxci_do_audio_callback(callNo, e->ts, IAXC_SOURCE_REMOTE, 0, 0, size, (unsigned char *)fr); } if ( iaxci_audio_output_mode ) continue; if (!test_mode) audio_driver.output(&audio_driver, fr, fr_samples - samples - mainbuf_delta); } while ( total_consumed < e->datalen ); }
void mysleep(void) { iaxc_millisleep(10); }
int main (int argc, char *argv[]) { int numbytes; static char buf[MAXBUFLEN]; //int c; //int ret = 0; prog = strdup( base_name(argv[0]) ); /* program header */ std::cout << prog << " - a communication radio based on VoIP with IAX/Asterisk" << std::endl; std::cout << "Original (c) 2007-2011 by H. Wirtz <*****@*****.**>" << std::endl; std::cout << "OSX and Windows ports 2012 by Yves Sablonier and Geoff R. McLane, respectively." << std::endl; std::cout << "Version " << FGCOM_VERSION << " build " << SVN_REV << " date " << __DATE__ << ", at " << __TIME__ << std::endl; std::cout << "Using iaxclient library Version " << iaxc_version (tmp) << std::endl; std::cout << std::endl; /* init values */ voipserver = DEFAULT_VOIP_SERVER; fgserver = DEFAULT_FG_SERVER; port = DEFAULT_FG_PORT; username = DEFAULT_USER; password = DEFAULT_PASSWORD; codec_option = DEFAULT_CODEC; mode = 0; /* 0 = ATC mode, 1 = FG mode */ positions_file = (char *) DEFAULT_POSITIONS_FILE; frequency_file = (char *) SPECIAL_FREQUENCIES_FILE; #ifndef _WIN32 /* catch signals */ signal (SIGINT, quit); signal (SIGQUIT, quit); signal (SIGTERM, quit); #endif /* setup iax */ #ifdef HAVE_IAX12 if (iaxc_initialize (DEFAULT_MAX_CALLS)) #else if (iaxc_initialize (DEFAULT_IAX_AUDIO, DEFAULT_MAX_CALLS)) #endif fatal_error ("cannot initialize iaxclient!\nHINT: Have you checked the mic and speakers?"); initialized = 1; // option parser fgcomInitOptions (fgcomOptionArray, argc, argv); // codec if (codec_option) { switch (codec_option) { case 'u': codec = IAXC_FORMAT_ULAW; break; case 'a': codec = IAXC_FORMAT_ALAW; break; case 'g': codec = IAXC_FORMAT_GSM; break; case '7': codec = IAXC_FORMAT_G726; break; case 's': codec = IAXC_FORMAT_SPEEX; break; } } // airport if (airport_option) { strtoupper (airport_option, airport, sizeof (airport)); } // input level if (level_in > 1.0) { level_in = 1.0; } if (level_in < 0.0) { level_in = 0.0; } // output level if (level_out > 1.0) { level_out = 1.0; } if (level_out < 0.0) { level_out = 0.0; } // microphone boost if (mic_boost) { iaxc_mic_boost_set (1); } if (list_audio) { std::cout << "Input audio devices:" << std::endl; std::cout << report_devices (IAXC_AD_INPUT) << std::endl; std::cout << "Output audio devices:" << std::endl; std::cout << report_devices (IAXC_AD_OUTPUT) << std::endl; iaxc_shutdown (); exit (1); } if (audio_in) { set_device (audio_in, 0); } if (audio_out) { set_device (audio_out, 1); } //#ifdef DEBUG /* Print any remaining command line arguments (not options). */ //if (optind < argc) { // printf ("non-option ARGV-elements: "); // while (optind < argc) // printf ("%s ", argv[optind++]); // putchar ('\n'); //} //#endif /* checking consistency of arguments */ if (frequency > 0.0 && frequency < 1000.0) { if (strlen (airport) == 0 || strlen (airport) > 4) { strcpy (airport, "ZZZZ"); } /* airport and frequency are given => ATC mode */ mode = 0; } else { /* no airport => FG mode */ mode = 1; } /* Read special frequencies file (if exists). * If no file $(INSTALL_DIR)/special_frequencies.txt exists, then default frequencies * are used and are hard coded. */ if (fix_input_files()) { /* adjust default input per OS */ fatal_error ("cannot adjust default input files per OS!\nHINT: Maybe recompile with larger buffer."); } if((special_frequencies = read_special_frequencies(frequency_file)) == 0) { std::cout << "Failed to load file [" << frequency_file << "]!\nUsing internal defaults." << std::endl; special_frequencies = special_frq; } else { std::cout << "Loaded file [" << frequency_file << "]." << std::endl; } /* read airport frequencies and positions */ airportlist = read_airports (positions_file); /* never returns if fail! */ /* preconfigure iax */ std::cout << "Initializing IAX client as " << username << ":" << "xxxxxxxxxxx@" << voipserver << std::endl; iaxc_set_callerid (const_cast < char *>(username), const_cast < char *>("0125252525122750")); iaxc_set_formats (codec, IAXC_FORMAT_ULAW | IAXC_FORMAT_GSM | IAXC_FORMAT_SPEEX); iaxc_set_event_callback (iaxc_callback); iaxc_start_processing_thread (); if (username && password && voipserver) { reg_id = iaxc_register (const_cast < char *>(username), const_cast < char *>(password), const_cast < char *>(voipserver)); #ifdef DEBUG std::cout << "DEBUG: Registered as '" << username << "' at '" << voipserver << "'." << std::endl; #endif } else { std::cout << "Failed iaxc_register!\nHINT: Check user name, pwd and ip of server." << std::endl; exitcode = 130; quit (0); } iaxc_millisleep (DEFAULT_MILLISLEEP); /* main loop */ #ifdef DEBUG std::cout << "Entering main loop in mode " << mode_map[mode] << "." << std::endl; #endif if (mode == 1) { /* only in FG mode */ netInit (); netSocket fgsocket; fgsocket.open (false); fgsocket.bind (fgserver, port); /* mute mic, speaker on */ iaxc_input_level_set (0); iaxc_output_level_set (level_out); ulClock clock; clock.update (); double next_update = clock.getAbsTime () + DEFAULT_ALARM_TIMER; /* get data from flightgear */ while (1) { clock.update (); double wait = next_update - clock.getAbsTime (); if (wait > 0.001) { netSocket *readsockets[2] = { &fgsocket, 0 }; if (fgsocket.select (readsockets, readsockets + 1, (int) (wait * 1000)) == 1) { netAddress their_addr; if ((numbytes = fgsocket.recvfrom (buf, MAXBUFLEN - 1, 0, &their_addr)) == -1) { perror ("recvfrom"); exit (1); } buf[numbytes] = '\0'; #ifdef DEBUG std:: cout << "DEBUG: got packet from " << their_addr.getHost () << ":" << their_addr.getPort () << std::endl; std::cout << "packet is " << numbytes << " bytes long" << std::endl; std:: cout << "packet contains \"" << buf << "\"" << std::endl; #endif process_packet (buf); } } else { alarm_handler (0); clock.update (); next_update = clock.getAbsTime () + DEFAULT_ALARM_TIMER; } } } else { /* only in ATC mode */ struct pos p; /* mic on, speaker on */ iaxc_input_level_set (level_in); iaxc_output_level_set (level_out); /* get geo positions of the airport */ p = posbyicao (airportlist, airport); icao2number (airport, frequency, tmp); #ifdef DEBUG printf ("DEBUG: dialing %s %3.3f MHz: %s\n", airport, frequency, tmp); #endif do_iaxc_call (username, password, voipserver, tmp); /* iaxc_select_call (0); */ while (1) { /* sleep endless */ ulSleep (3600); } } /* should never be reached */ exitcode = 999; quit (0); }
void process_packet (char *buf) { /* cut off ending \n */ buf[strlen (buf) - 1] = '\0'; /* parse the data into a struct */ parse_fgdata (&data, buf); /* get the selected frequency */ if (com_select == 0 && data.COM1_SRV == 1) selected_frequency = data.COM1_FRQ; else if (com_select == 1 && data.NAV1_SRV == 1) selected_frequency = data.NAV1_FRQ; else if (com_select == 2 && data.COM2_SRV == 1) selected_frequency = data.COM2_FRQ; else if (com_select == 3 && data.NAV2_SRV == 1) selected_frequency = data.NAV2_FRQ; /* Check for com frequency changes */ if (previous_com_frequency != selected_frequency) { printf ("Selected frequency: %3.3f\n", selected_frequency); /* remark the new frequency */ previous_com_frequency = selected_frequency; if (connected == 1) { /* hangup call, if connected */ iaxc_dump_call (); iaxc_millisleep (5 * DEFAULT_MILLISLEEP); connected = 0; } strcpy (icao, icaobypos (airportlist, selected_frequency, data.LAT, data.LON, DEFAULT_RANGE)); icao2number (icao, selected_frequency, tmp); #ifdef DEBUG printf ("DEBUG: dialing %s %3.3f MHz: %s\n", icao, selected_frequency, tmp); #endif do_iaxc_call (username, password, voipserver, tmp); /* iaxc_select_call (0); */ connected = 1; } /* Check for pressed PTT key */ if (previous_ptt != data.PTT) { if (data.PTT == 2) { /* select the next com equipment */ com_select = (com_select + 1) % 4; printf ("Radio-Select: %s\n", radio_map[com_select]); } else if (connected == 1) { ptt (data.PTT); } previous_ptt = data.PTT; } }