#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>

#include "drv.h"

#define AD_BUFFER_SIZE  8192	// 512 * 16
#define DA_BUFFER_SIZE  512	// 512 * 1

static int   ad_data[AD_BUFFER_SIZE];
static short da_data[DA_BUFFER_SIZE];

static int main_end_flag;

typedef struct
{
	char		riff[4];	// = "RIFF"
	unsigned long	total_size;	// 全体サイズ
	char		fmt[8];		// "WAVEfmt "
	unsigned long	fmt_size;	// fmt チャンクサイズ
	unsigned short	format;		// フォーマットの種類
	unsigned short	channel;	// チャンネル
	unsigned long	rate;		// サンプリングレート
	unsigned long	avgbyte;	// rate * block
	unsigned short	block;		// channels * bit / 8
	unsigned short	bit;		// ビット数
	char		data[4];	// = "data"
	unsigned long	data_size;	// データサイズ
} WAVEFORMAT;

void sigint_action(int signum, siginfo_t *info, void *ctx)
{
//    printf("sigint_handler(%d): signo(%d) code(0x%x)\n",
//           signum, info->si_signo, info->si_code);
    
    main_end_flag = 1;
}


int main(int argc, char **argv)
{
    struct sigaction sa_sigint;
    
    int fd;
    int stat;
    
    int    ret_val;
    struct timeval time_out;
    fd_set rfds, wfds;
    
    int rbyte;
    int wbyte;
    
    char device_name[64];

    int i, j, rdcnt;

    FILE *fp;
    fpos_t pos;
    WAVEFORMAT header;

    if(argc == 2)
    {
        strcpy(device_name, argv[1]);
    }
    else
    {
        strcpy(device_name, "/dev/kt");
    }
    fd = open(device_name, O_RDWR, 0666);
    if(fd < 0)
    {
        printf("%s open error.\n", device_name);
        return -1;
    }
    
    memset( &header, 0, sizeof(header) );
    strncpy( header.riff, "RIFF", 4 );
    header.total_size = sizeof( header );
    strncpy( header.fmt, "WAVEfmt ", 8 );
    header.fmt_size = 16;
    header.format = 1;	/* PCM */
    header.channel = 16;
    header.rate = 16000;
    header.bit = 24;
    header.block = header.channel * header.bit / 8;
    header.avgbyte = header.rate * header.block;
    strncpy( header.data, "data", 4 );
    header.data_size = 0;
    header.total_size = sizeof( header );

    /* Open file */
    if ((fp = fopen("/tmp/record.wav","wb")) == NULL ) {
        printf("file open error!\n");
        close( fd );
        return -1;
    }
    fgetpos( fp, &pos );
    if( fwrite( &header, sizeof( header ), 1, fp ) < 1 ) {
        printf("file write error!\n");
        close( fd );
        fclose( fp );
        return -1;
    }
    
    stat = ioctl(fd, FIO_AD_START);
    if(stat < 0)
    {
	printf("ioctl error! (%d)\n", stat);
	close ( fd );
	return -1;
    }
    
    memset(&sa_sigint, 0, sizeof(sa_sigint));
    sa_sigint.sa_sigaction = sigint_action;
    sa_sigint.sa_flags = SA_RESTART | SA_SIGINFO;
    
    if (sigaction(SIGINT, &sa_sigint, NULL) < 0)
    {
        printf("sigaction error.\n");
    }

    rdcnt = 0;
    while(!main_end_flag)
    {
        do
        {
            FD_ZERO(&rfds);
            FD_ZERO(&wfds);
            FD_SET(fd, &rfds);
            FD_SET(fd, &wfds);
            
            time_out.tv_sec  = 0;
            time_out.tv_usec = 10 * 1000;
            ret_val = select(fd+1, &rfds, &wfds, NULL, &time_out);
        }while(ret_val == 0);
        
        if(ret_val < 0)
        {
            printf("ret_val = %d\n", ret_val);
            main_end_flag = 1;
            break;
        }

        /* データ取得処理 */
        if(FD_ISSET(fd, &rfds))
        {
            rbyte = read(fd, &ad_data[0], sizeof(ad_data));
            for( i = 0 ; i < (rbyte / sizeof(int)) ; i++ )
            {
#if 1
                if( fwrite( &ad_data[i], header.bit / 8, 1, fp ) < 1 )
                {
                    printf("file full!\n");
                    main_end_flag = 1;
                    break;
                }
                header.data_size += ( header.bit / 8 );
#endif
#if 0
                if(( rdcnt % 32 ) == 0 )
                {
                    da_data[(rdcnt / 32)] = (short)(ad_data[i] >> 4);
                }
                rdcnt++;
#endif
            }
        }
#if 0
        /* データ書き込み処理 */
        if(FD_ISSET(fd, &wfds))
        {
            if( rdcnt / 32 )
            {
                wbyte = write(fd, &da_data[0], (rdcnt / 32 * sizeof(short)));
                if( wbyte != (rdcnt / 32 * sizeof(short)))
                {
                    printf("write wave lost! (%d %d)\n", rdcnt, wbyte);
                }
                rdcnt %= 32;
            }
        }
#endif
    }
    
    stat = ioctl(fd, FIO_AD_STOP);
    if(stat < 0)
    {
	printf("ioctl error! (%d)\n", stat);
    }

    close(fd);

    /* Write Wave Header */
    header.total_size += header.data_size;
    fsetpos( fp, &pos );
    fwrite( &header, sizeof( header ), 1, fp );

    /* Close device */
    fclose( fp );

    printf("TOTAL SIZE = %d [MiB]\n", header.total_size/1024/1024);
    
    return 0;
}

/* EOF */

