Example #1
0
static int do_level_callback()
{
	static struct timeval last = {0,0};
	struct timeval now;
	float input_db;
	float output_db;

	now = iax_tvnow();

	if ( last.tv_sec != 0 && iaxci_usecdiff(&now, &last) < 100000 )
		return 0;

	last = now;

	/* if input has not been processed in the last second, set to silent */
	input_db = iaxci_usecdiff(&now, &timeLastInput) < 1000000 ?
			vol_to_db(input_level) : AUDIO_ENCODE_SILENCE_DB;

	/* if output has not been processed in the last second, set to silent */
	output_db = iaxci_usecdiff(&now, &timeLastOutput) < 1000000 ?
		vol_to_db(output_level) : AUDIO_ENCODE_SILENCE_DB;

	iaxci_do_levels_callback(input_db, output_db);

	return 0;
}
Example #2
0
static int service_audio()
{
	/* TODO: maybe we shouldn't allocate 8kB on the stack here. */
	short buf [4096];

	int want_send_audio =
		selected_call >= 0 &&
		((calls[selected_call].state & IAXC_CALL_STATE_OUTGOING) ||
		 (calls[selected_call].state & IAXC_CALL_STATE_COMPLETE));
		//&& !(audio_prefs & IAXC_AUDIO_PREF_SEND_DISABLE);

	int want_local_audio =
		(audio_prefs & IAXC_AUDIO_PREF_RECV_LOCAL_RAW) ||
		(audio_prefs & IAXC_AUDIO_PREF_RECV_LOCAL_ENCODED);

	//fprintf(stdout, "service_audio() => want_send_audio=%d/want_local_audio=%d\n", want_send_audio, want_local_audio);

	if ( want_local_audio || want_send_audio )
	{
		for ( ;; )
		{
			int to_read;
			int cmin;

			audio_driver.start(&audio_driver);

			/* use codec minimum if higher */
			cmin = want_send_audio && calls[selected_call].encoder ?
				calls[selected_call].encoder->minimum_frame_size :
				1;

			to_read = cmin > minimum_outgoing_framesize ?
				cmin : minimum_outgoing_framesize;

			/* Round up to the next multiple */
			if ( to_read % cmin )
				to_read += cmin - (to_read % cmin);

			if ( to_read > (int)(sizeof(buf) / sizeof(short)) )
			{
				fprintf(stderr,
					"internal error: to_read > sizeof(buf)\n");
				exit(1);
			}

			/* Currently pa gives us either all the bits we ask for or none */
			if ( audio_driver.input(&audio_driver, buf, &to_read) )
			{
				iaxci_usermsg(IAXC_ERROR, "ERROR reading audio\n");
				break;
			}

			/* Frame was not available */
			if ( !to_read )
				break;

			if ( audio_prefs & IAXC_AUDIO_PREF_RECV_LOCAL_RAW )
				iaxci_do_audio_callback(selected_call, 0,
						IAXC_SOURCE_LOCAL, 0, 0,
						to_read * 2, (unsigned char *)buf);

			if (( want_send_audio ) && (!(audio_prefs & IAXC_AUDIO_PREF_SEND_DISABLE)))
				audio_send_encoded_audio(&calls[selected_call],
						selected_call, buf,
						calls[selected_call].format &
							IAXC_AUDIO_FORMAT_MASK,
						to_read);
		}
	}
	else
	{
		static int i = 0;

		audio_driver.stop(&audio_driver);

		/*!
			\deprecated
			Q: Why do we continuously send IAXC_EVENT_LEVELS events
		   when there is no selected call?

		 A: So that certain users of iaxclient do not have to
		   reset their vu meters when a call ends -- they can just
		   count on getting level callbacks. This is a bit of a hack
		   so any applications relying on this behavior should maybe
		   be changed.
		 */
		if ( i++ % 50 == 0 )
			iaxci_do_levels_callback(AUDIO_ENCODE_SILENCE_DB,
					AUDIO_ENCODE_SILENCE_DB);
	}

	return 0;
}