#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <assert.h>
#include <stdbool.h>
#include "soundio-class.h"

#define CHECK_RESULT_FULL(tag, ret, verbose) do {	\
	bool _r = (ret);				\
	if (!_r || (verbose))				\
		printf("%s%s... %s\n",			\
		       (tag), #ret,			\
		       _r ? "OK" : "Failed");		\
	if (!_r) goto fail;				\
} while (0)

#define CHECK_RESULT(ret) CHECK_RESULT_FULL("", (ret), true)
#define CHECK_FAIL(ret) CHECK_RESULT_FULL("", (ret), false)

static int record_callback(const char *data, const unsigned long len, void *user_data)
{
	FILE *file = user_data;

	assert(fwrite(data, len, 1, file) == 1);
	fflush(file);

	return 0; /* not used, right now */
}

static int played_notify(void *user_data)
{
	int tag = (int) (intptr_t) user_data;

	printf("%s:%d\n", __func__, tag);

	return 0;
}

static char *format_bytes(int bytes)
{
	static char buf[1024] = { 0, 0 };
	int M, K, B;
	char *ptr = buf;
#define MILLION (1024 * 1024)
#define KILO (1024)

	M = bytes/MILLION;
	K = (bytes % MILLION) / KILO;
	B = bytes % KILO;

	if (M)
		ptr += sprintf(ptr, "%dM", M);
	if (K)
		ptr += sprintf(ptr, "%dk", K);
	if (B)
		ptr += sprintf(ptr, "%d", K);

	return buf;
}

int main(int argc, char *argv[], char *envp[])
{
	tagSoundIn in;
	tagSoundOut out;
	FILE *sample_file;
	int i;
	char *tmp;
	size_t cnt, total;
	int volume, volumes[2] = { 45, 80 };

	ignore_signals(SIGPIPE, -1);

	sample_file = fopen("sample.pcm", "w+");
	assert(sample_file);

	CHECK_RESULT(SoundIn_init(&in));
	in.WaveInCallback = record_callback;
	in.user_data = sample_file;
	in.stop_wait = 250 * 1000;

	CHECK_RESULT(SoundOut_init(&out));
	out.WaveOutCallback = played_notify;
	out.stop_wait = 250 * 1000;

	puts("--------------------------------------------------");
	puts("######## Recording Test ########");
	puts("Start recording for 5 secs");
	CHECK_RESULT(SoundIn_start(&in));
	sleep(5);
	CHECK_RESULT(SoundIn_stop(&in));
	CHECK_RESULT(SoundIn_uninit(&in));

	puts("--------------------------------------------------");
	puts("######## Play Test ########");
	CHECK_RESULT(SoundOut_start(&out));

	rewind(sample_file);
	i = 0, total = 0;
	do {
		assert((tmp = malloc(1024 * 20)) != NULL);
		if ((cnt = fread(tmp, 1, 1024 * 20, sample_file)) <= 0) {
			free(tmp);
			break;
		}
		total += cnt;
		CHECK_FAIL(SoundOut_play_data(&out, tmp, cnt, (void *) (intptr_t) i));
		printf("\rFilled %s data.", format_bytes(total));
		fflush(stdout);

		i++;
	} while(true);
	puts("\nWait for playback end...");
	sleep(7);

	volume = SoundOut_get_volume(&out);
	printf("Volume is %d%%\n", volume);

	for (i = 0; i < sizeof(volumes)/sizeof(volumes[0]); i++) {
		volume = volumes[i];

		printf("Volume set to %d%%\n", volume);
		CHECK_RESULT(SoundOut_set_volume(&out, volume));
	}

	CHECK_RESULT(SoundOut_stop(&out));
	CHECK_RESULT(SoundOut_uninit(&out));

	return 0;

fail:
	return 1;
} 

