#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>

#include <gtk/gtk.h>

#include <pulse/pulseaudio.h>
#include <pulse/glib-mainloop.h>

#define APP_TITLE "Test 5 lpo"
#define BUFSIZE 1024

pa_context *context;

void create_stream();

static void stream_state_callback(pa_stream *s, void *unused) {
	switch (pa_stream_get_state(s)) {
		case PA_STREAM_UNCONNECTED:
		case PA_STREAM_CREATING:
			break;

		case PA_STREAM_READY:
			printf("PA_STREAM_READY\n");
/*
			g_assert(!mainWindow);
			mainWindow = new MainWindow(*pa_stream_get_channel_map(s), device_name, device_description);

			g_timeout_add(100, latency_func, NULL);
			pa_operation_unref(pa_stream_update_timing_info(stream, stream_update_timing_info_callback, NULL));
*/
			break;

		case PA_STREAM_FAILED:
			printf("PA_STREAM_FAILED\n");
			break;

		case PA_STREAM_TERMINATED:
			printf("PA_STREAM_TERMINATED\n");
			//Gtk::Main::quit();
	}
}

static void context_get_source_info_callback(pa_context *c, const pa_source_info *si, int is_last, void *unused) {
	printf("context_get_source_info_callback\n");

	if (is_last < 0) {
		printf("Failed to get source information");
		return;
	}

	if (!si)
		return;

	create_stream(si->name, si->description, si->sample_spec, si->channel_map);
}

static void context_get_sink_info_callback(pa_context *c, const pa_sink_info *si, int is_last, void *unused) {
	printf("context_get_sink_info_callback\n");
	if (is_last < 0) {
		printf("Failed to get sink information");
		return;
	}

	if (!si)
		return;

	create_stream(si->monitor_source_name, si->description, si->sample_spec, si->channel_map);
}


static void stream_read_callback(pa_stream *s, size_t l, void *unused) {
	const void *p;

	if (pa_stream_peek(s, &p, &l) < 0) {
		printf("pa_stream_peek() failed: %s", pa_strerror(pa_context_errno(context)));
		return;
	}

	printf("%f, %i\n", *((const float*)p), l/sizeof(float));

	pa_stream_drop(s);
}

static void context_state_callback(pa_context *c, void *unused) {
	switch (pa_context_get_state(c)) {
		case PA_CONTEXT_UNCONNECTED:
			printf("PA_CONTEXT_UNCONNECTED\n");
			break;
		case PA_CONTEXT_CONNECTING:
			printf("PA_CONTEXT_CONNECTING\n");
			break;
		case PA_CONTEXT_AUTHORIZING:
			printf("PA_CONTEXT_AUTHORIZING\n");
			break;
		case PA_CONTEXT_SETTING_NAME:
			printf("PA_CONTEXT_SETTING_NAME\n");
			break;

		case PA_CONTEXT_READY:
			printf("PA_CONTEXT_READY\n");
			g_assert(!stream);

			//if (device_name && mode == RECORD)
			//pa_operation_unref(pa_context_get_source_info_by_name(c, device_name, context_get_source_info_callback, NULL));
			/*else if (device_name && mode == PLAYBACK)
				pa_operation_unref(pa_context_get_sink_info_by_name(c, device_name, context_get_sink_info_callback, NULL));
			else
				pa_operation_unref(pa_context_get_server_info(c, context_get_server_info_callback, NULL));
			*/
			break;

		case PA_CONTEXT_FAILED:
			printf("PA_CONTEXT_FAILED\n");
			break;

		case PA_CONTEXT_TERMINATED:
			printf("PA_CONTEXT_TERMINATED\n");
			break;
	}
}

void create_stream(const char *name, const char *description, const pa_sample_spec *ss, const pa_channel_map *cmap) {
	/* The sample type to use */
	static const pa_sample_spec nss = {
		.format = PA_SAMPLE_S16LE,
		.rate = 44100,
		.channels = 1
	};

	pa_stream *stream=NULL;
	char t[256];
/*
	g_free(device_name);
	device_name = g_strdup(name);
	g_free(device_description);
	device_description = g_strdup(description);
*/

	printf("Using sample format: %s", pa_sample_spec_snprint(t, sizeof(t), &nss));
	printf("Using channel map: %s", pa_channel_map_snprint(t, sizeof(t), cmap));

	stream = pa_stream_new(context, APP_TITLE, &nss, cmap);
	pa_stream_set_state_callback(stream, stream_state_callback, NULL);
	pa_stream_set_read_callback(stream, stream_read_callback, NULL);
	pa_stream_connect_record(stream, name, NULL, (enum pa_stream_flags) 0);
}


int main(int argc, char*argv[]) {
	int res, retval;
/*
	int error;
	int i,j;
	float sum;
	g_thread_init(NULL);
	gdk_threads_init();
	gdk_threads_enter();
	gtk_init (&argc, &argv);
*/

/*	pa_glib_mainloop *m;
	m = pa_glib_mainloop_new(g_main_context_default()); g_assert(m);
	context = pa_context_new(pa_glib_mainloop_get_api(m), APP_TITLE); g_assert(context);
*/
	pa_mainloop *m;
	m=pa_mainloop_new(); g_assert(m);
        context = pa_context_new(pa_mainloop_get_api(m), APP_TITLE); g_assert(context);

	pa_context_set_state_callback(context, context_state_callback, NULL);
	pa_context_connect(context, NULL, PA_CONTEXT_NOAUTOSPAWN, NULL);

	res=pa_mainloop_run(m,&retval);
	g_assert(res==0);
	pa_mainloop_free(m);

//	gtk_main ();
//	gdk_threads_leave();

	return 0;

}