Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
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);
}
Ejemplo n.º 3
0
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);
	}
}
Ejemplo n.º 4
0
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;
}
Ejemplo n.º 5
0
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;
    }
}
Ejemplo n.º 6
0
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 );
}
Ejemplo n.º 7
0
void mysleep(void)
{
	iaxc_millisleep(10);
}
Ejemplo n.º 8
0
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);
}
Ejemplo n.º 9
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;
    }
}