#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <soundcard.h>
#include <stdio.h>
#include <stdlib.h>
/* Example of how to read input from C on the gp2x wiz */
/* by fells on gp32x.de */
static int mixer_fd = -1;
int fd_in;
FILE* file_out;
float seconds = 0;
#define SAMPLE_RATE 22050
#define BUF_SAMPLES 16384
static int mixer_open(const char *device) {
        mixer_fd = open(device, O_RDWR);
        if (mixer_fd == -1) return -1;
	return 0;
}
static int mixer_set_recsrc(int channel) {
	if(ioctl(mixer_fd, SOUND_MIXER_WRITE_RECSRC, &channel) == -1) return -1;
	return 0;
}
static int mixer_set_level(int channel, int l, int r) {
        int tmp;
        tmp = (l & 0x7f) + ((r & 0x7f) << 8);
        if (ioctl(mixer_fd, MIXER_WRITE(channel), &tmp) == -1) return -1;
        return 0;
}
static int open_audio_device (char *name, int mode) {
	int fd;
	if ((fd = open (name, mode, 0)) == -1) {
		perror (name);
		exit (-1);
	}
	int format = AFMT_S16_NE;		/* Native 16 bits */
	if (ioctl (fd, SNDCTL_DSP_SETFMT, &format) == -1)   {
		perror ("SNDCTL_DSP_SETFMT");
		exit (-1);
	}
	int channels = 2; // have to use 2 channels on pollux
	if (ioctl (fd, SNDCTL_DSP_CHANNELS, &channels) == -1) {
		perror ("SNDCTL_DSP_CHANNELS");
		exit (-1);
	}
	int sample_rate = SAMPLE_RATE;
	if (ioctl (fd, SNDCTL_DSP_SPEED, &sample_rate) == -1) {
		perror ("SNDCTL_DSP_SPEED");
		exit (-1);
	}
	return fd;
}
void process_input (void) {
	short buffer[BUF_SAMPLES];
	int bytes_read, samples_read, frames_read, i, level_min, level_max;
	if ((bytes_read = read (fd_in, buffer, sizeof (buffer))) == -1) {
		perror ("Audio read");
		exit (-1);		/* Or return an error code */
	}
	samples_read = bytes_read / 2; // 2 bytes per sample
	frames_read = samples_read / 2; // because we are reading stereo data
	level_max = 0;
	level_min = 16384;
	for (i = 0; i < samples_read; i=i+1) {
		int v = buffer[i];
		if (v > level_max) level_max = v;
		if(v < level_min) level_min = v;
	}
	fwrite(buffer, sizeof(short), samples_read, file_out);
	fflush (stdout);
	seconds = seconds + ((float)frames_read/22050.0);
	printf("(%d,%d) %2.2f\n", level_min, level_max,seconds);
}
int main(int argc, char**argv) {
	int i;
	// Open the mixer and the audio device
	i = mixer_open("/dev/mixer");
	fd_in = open_audio_device ("/dev/dsp", O_RDONLY);
	// Set the recording source to mic
	i = mixer_set_recsrc(SOUND_MIXER_MIC);
	i = mixer_set_level(SOUND_MIXER_VOLUME, 100, 100);
	// Debug note: there seems to be a bug in the pollux driver that the mic setting can't be "gotten"
	// with the SOUND_MIXER_MIC -- for some reason, you need to get the mixer gain with SOUND_MIXER_LINE
	// But you should still set the gain with SOUND_MIXER_MIC. See pollux-cs42L51.c
	i = mixer_set_level(SOUND_MIXER_MIC, 85, 85); // the built in voice recorder sets mixer vol to 85 too
	sleep(1);
	char filename[255];
	if(argc != 2) {
		strcpy(filename, "/mnt/sd/out-sound.raw");
	} else {
		strcpy(filename, argv[1]);
	}
	file_out = fopen(filename,"w");
	// Start recording
	while (seconds < 10)
	    process_input ();
	fclose(file_out);
	exit (0);
}