#include "player.h"
#include"SDFileSystem.h"

SDFileSystem sd(D11, D12, D13, D10, "sd"); // the pinout on the mbed Cool
vs10xx vs1053(D11, D12, D13, A3, A2, A1, A0);//mosi,miso,sclk,xcs,xdcs,dreq,xreset

playerStatetype  playerState;
ctrlStatetype ctrlState;
static unsigned char fileBuf[1024];
unsigned char *bufptr;

char list[15][14];            //song list
char index = 0;      //song play index
char index_MAX;      //how many song in all
unsigned char vlume = 0x40;   //vlume
unsigned char vlumeflag = 0;  //set vlume flag

void Player::begin(void)
{
    DirHandle *dir;
    struct dirent *ptr;
		FileHandle *fp;
   
    vs1053.reset();
    dir = opendir("/sd");
    printf("\r\n**********playing list**********\r\n");
    unsigned char i = 0,j=0;
    while(((ptr = dir->readdir()) != NULL)&&(i <15))
    {
        if(strstr(ptr->d_name,".mp3")||strstr(ptr->d_name,".MP3")||strstr(ptr->d_name,".WAV")||strstr(ptr->d_name,".wav")
            ||strstr(ptr->d_name,".WMA")||strstr(ptr->d_name,".wma")||strstr(ptr->d_name,".OGG")||strstr(ptr->d_name,".ogg")
            ||strstr(ptr->d_name,".AAC")||strstr(ptr->d_name,".aac")||strstr(ptr->d_name,".FLAC")||strstr(ptr->d_name,".flac"))
        {
							fp =sd.open(ptr->d_name, O_RDONLY);
							if(fp != NULL) 
							{
								char *byte = ptr->d_name;
                j=0;
                while(*byte)
                {
                    list[i][j++]  = *byte++;
                }
                printf("%2d . %s\r\n", i,list[i++]);
								//fp->close();
							}
        }
    }
    index_MAX = i-1;
		dir->closedir();
    printf("\r\n");
}

/*  This function plays back an audio file.  */
void Player::playFile(char *file) {
    int bytes;        // How many bytes in buffer left
    char n;
  
    
    playerState = PS_PLAY;
    
    if (strstr(file, ".flac"))
    {
        printf("Loading FLAC Plugin...\r\n");
        vs1053.loadPlugin(flacPlugin,sizeof(flacPlugin)/sizeof(flacPlugin[0]));   
    }

    vs1053.setFreq(24000000);     //hight speed
     
    FileHandle *fp =sd.open(file, O_RDONLY);
    
    if(fp == NULL) {
        printf("Could not open %s\r\n",file);

    }
    else
    {
        printf("Playing %s ...\r\n",file);
        
        /* Main playback loop */
        while((bytes = fp->read(fileBuf,512)) > 0)
        {
            bufptr = fileBuf;
            
            // actual audio data gets sent to VS10xx.
            while(bytes > 0)
            {
                n = (bytes < 32)?bytes:32; 
                vs1053.writeData(bufptr,n);
                bytes -= n;
                bufptr += n;
            }
            while(playerState == PS_PAUSE);         //Pause
            
           if(vlumeflag)                          //set vlume
            {
                vs1053.setFreq(12000000);     //low speed
                vs1053.writeRegister(SPI_VOL, vlume*0x101);     //Set volume level
                vs1053.setFreq(24000000);     //higth speed
                vlumeflag = 0;  //clear flag;            
            }
            
            if(playerState != PS_PLAY)         //stop
            {
                fp->close();
                vs1053.softReset();
                return;
            }
        }
        fp->close();
        vs1053.softReset(); 
        printf("[done!]\r\n");
    }
    if(index != index_MAX)index++;
    else index = 0;
}


/* PCM file Header */
unsigned char pcmHeader[44] = {
  'R', 'I', 'F', 'F',
  0xFF, 0xFF, 0xFF, 0xFF,
  'W', 'A', 'V', 'E',
  'f', 'm', 't', ' ',
  0x10, 0, 0, 0,          /* 16 */
  0x1, 0,                 /* PCM */
  0x1, 0,                 /* chan */
  0x40, 0x1F, 0x0, 0x0,     /* sampleRate */
  0x80, 0x3E, 0x0, 0x0,     /* byteRate */
  2, 0,                   /* blockAlign */
  0x10, 0,                /* bitsPerSample */
  'd', 'a', 't', 'a',
  0xFF, 0xFF, 0xFF, 0xFF
};

void Set32(unsigned char *d, unsigned int n) {
  int i;
  for (i=0; i<4; i++) {
    *d++ = (unsigned char)n;
    n >>= 8;
  }
}

/*  This function records an audio file in WAV formats.Use LINK1,left channel  */
void Player::recordFile(char *file) {
    unsigned int fileSize = 0;
    unsigned int n;

    vs1053.writeRegister(SPI_BASS, 0x0055);    //set accent
    vs1053.writeRegister(SPI_AICTRL0,8000);    //samplerate 8k
    vs1053.writeRegister(SPI_AICTRL1,0);       //record gain
    vs1053.writeRegister(SPI_AICTRL2,0);       //Set the gain maximum,65536=64X
    vs1053.writeRegister(SPI_AICTRL3,7);       //PCM Mode ,left channel,earphone mic
    //vs1053.writeRegister(SPI_AICTRL3,6);     //PCM Mode ,right channel,board mic
    vs1053.writeRegister(SPI_CLOCKF,0x2000);   //set clock
    
    printf("loading recording plugin......\r\n");
    vs1053.writeRegister(SPI_MODE,0x1804);   //Initialize recording
    
    vs1053.loadPlugin(recPlugin,sizeof(recPlugin)/sizeof(recPlugin[0]));
    sd.remove(file);
    FileHandle *fp =sd.open(file, O_WRONLY|O_CREAT);
    if(fp == NULL) {
        printf("Could not open file for write\r\n");
    }
    else
    {
        printf("recording......\r\n");
        while(playerState == PS_RECORDING)
        {
            unsigned int i;
            unsigned char *rbp = fileBuf;
            /* See if there is some data available */
            if ((n = vs1053.readRegister(SPI_HDAT1)) > 0) {
                /* Make little-endian conversion for 16-bit PCM .WAV files */
                if(n>511)n=511;
                for (i=0; i<n;i++) {
                    unsigned int w = vs1053.readRegister(SPI_HDAT0);
                    *rbp++ = (unsigned char)(w & 0xFF);
                    *rbp++ = (unsigned char)(w >> 8);
                }
                fp->write(fileBuf,2*n);
                fileSize += 2*n;
            }
                
        } 
        
        /* Update file sizes for an RIFF PCM .WAV file */
        fp->lseek(0, SEEK_SET);
        Set32(pcmHeader+4, fileSize-8);
        Set32(pcmHeader+40, fileSize-36);
        fp->write(pcmHeader, sizeof(pcmHeader));
        fp->close();

        printf("recording end\r\n");
    }
    /* Finally, reset the VS10xx software, including realoading the
       patches package, to make sure everything is set up properly. */
    vs1053.softReset();

}
