/* sunplay.c - ©1998 Tom Erbe
   this code schleps samples off to the DACs */
#include <errno.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stropts.h>
#include <sys/param.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/audioio.h>
#include <sys/file.h>
#include <sys/filio.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <pthread.h>

#include "sunplay.h"
#include "synthesize.h"
 

/* Globals */
float    gSampleRate;
long    gPlaying;
int     gAudioDevice = -1; /* file descriptor for audio i/o device */

int StartSunPlay(void)
{
    long                 flag;
    short                 error;
    audio_info_t    audioInfo;
    pthread_t        playThread;
    void                *threadFunction;

    /* open the audio device - write only, non-blocking */
    flag = O_WRONLY|O_NONBLOCK;
    if ((gAudioDevice = open("/dev/audio", flag)) < 0)
        return (-1);

    /* use macro from audioio.h to initialize the audio info structure
        then set everything to the desired values
    */
    AUDIO_INITINFO(&audioInfo);
    audioInfo.play.sample_rate = 44100;
    audioInfo.play.channels = 2;
    audioInfo.play.precision = 16;
    audioInfo.play.encoding = AUDIO_ENCODING_LINEAR;
    audioInfo.play.gain = AUDIO_MAX_GAIN;
    audioInfo.play.balance = AUDIO_MID_BALANCE;
    error = ioctl(gAudioDevice, AUDIO_SETINFO, &audioInfo);

    /* set up the thread which does all the work, and start it up with pthread_create */
    threadFunction = SunPlayThread;
    gPlaying = 1;
    pthread_create(&playThread, NULL, threadFunction, NULL);
    return(0);
}

void SunPlayThread(void *arg)
{
    unsigned long pauseTime;
    long start, outcnt, rtn;
    short shortSams[SIZE_BLOCK];

    while(gPlaying)
    {
        Synthesize(shortSams, SIZE_BLOCK);
        start = 0;
        outcnt = SIZE_BLOCK * sizeof(short);

        while (outcnt > 0)
        {
        /* write as much data as possible */
            rtn = write(gAudioDevice, (char *)&shortSams[start], outcnt);
            if (rtn > 0)
            {
                outcnt -= rtn;
                start += rtn;
            }
            else
            {
                /* give the DAC some time to empty,
                    til a quarter of the block has drained.
                    1000000 is to convert from seconds to microseconds*/
                pauseTime = (SIZE_BLOCK * 1000000)/(44100 * 4);
                usleep(pauseTime);
            }
        }
    }
}

void StopSunPlay(void)
{
    gPlaying = 0;
    close(gAudioDevice);
    gAudioDevice = -1;
}