#include "Sound_Player.h"
#include "Sound_Track_Playback.h"
#include "Sound_Source.h"
#include "IIS_MAX98357.h"

SoundPlayCtrlStruct     SoundPlayCtrl;

void Sound_Player_Init(void)
{
  SoundPlayCtrl.Playing = SND_SRC_NONE;               //加载要播放的声音
  SoundPlayCtrl.Timer   = 0;
  SoundPlayCtrl.Cycle   = 0;
  SoundPlayCtrl.Status  = SND_PLAYER_PLAYING;
  I2S_MAX98357_Init();
}

uint8_t Sound_Play(uint8_t SoundID)
{
  if (SoundID < SND_TOTAL_NUM)
  {    
    if (SoundPlayCtrl.Status != SND_PLAYER_IDLE)      //如果有声音正在播放,则返回播放失败
      return 1;
      
    SoundPlayCtrl.Playing = SoundID;                  //加载要播放的声音
    SoundPlayCtrl.Timer   = 0;
    SoundPlayCtrl.Cycle   = SndAttributeTable[SoundID].Cycle;
    SoundPlayCtrl.Status  = SND_PLAYER_PLAY_REQ;

    return 0;                                         //返回播放成功
  }
  return 2;                                           //返回错误状态
}

uint8_t Sound_Stop(uint8_t SoundID)
{
  if (SoundID < SND_TOTAL_NUM)
  {
    if ((SoundPlayCtrl.Status == SND_PLAYER_IDLE) || \
        (SoundPlayCtrl.Playing != SoundID))           //如果播放器已停止播放或正在播放的声音不是请求停止播放的声音
      return 0;                                       //返回停止成功
    
    if (SoundPlayCtrl.Status == SND_PLAYER_PLAY_REQ)  //请求停止播放的声音是刚请求播放的声音
    {

      SoundPlayCtrl.Playing = SND_SRC_NONE;
      SoundPlayCtrl.Timer   = 0;
      SoundPlayCtrl.Cycle   = 0;
      SoundPlayCtrl.Status = SND_PLAYER_IDLE;         //取消播放请求
      
      return 0;                                       //返回停止成功
    }
    
    SoundPlayCtrl.Status = SND_PLAYER_STOP_REQ;       //请求停止播放声音
    return 1;                                         //返回停止失败
  }
  
  return 2;                                           //返回错误状态
}

void Sound_Clear(void)
{
  if (SoundPlayCtrl.Status == SND_PLAYER_IDLE)
    return;
  
  if (SoundPlayCtrl.Status == SND_PLAYER_PLAY_REQ)
  {

    SoundPlayCtrl.Playing = SND_SRC_NONE;
    SoundPlayCtrl.Timer   = 0;
    SoundPlayCtrl.Cycle   = 0;
    SoundPlayCtrl.Status = SND_PLAYER_IDLE;           //取消播放请求
    return;
  }
  
  if (SoundPlayCtrl.Playing < SND_TOTAL_NUM)
    Snd_PCM_Track_Stop_Play(0);
  
  SoundPlayCtrl.Playing = SND_SRC_NONE;
  SoundPlayCtrl.Timer   = 0;
  SoundPlayCtrl.Cycle   = 0;
  SoundPlayCtrl.Status = SND_PLAYER_IDLE;             //取消播放请求
}

uint8_t Sound_Priority_Query(uint8_t SoundID)
{
  if (SoundID == SND_SRC_CURRENT)
  {
    if (SoundPlayCtrl.Playing < SND_TOTAL_NUM)
      return SndAttributeTable[SoundPlayCtrl.Playing].Priority;
    else
      return 0xFF;
  }
  
  if (SoundID < SND_TOTAL_NUM)
    return SndAttributeTable[SoundID].Priority;

  return 0xFF;
}

//10ms
void Sound_Play_Service(void)
{
  switch (SoundPlayCtrl.Status)
  {
    default                   : 
    case SND_PLAYER_IDLE      : break;
    
    case SND_PLAYER_PLAY_REQ  : if ((SoundPlayCtrl.Cycle != 0) && \
                                    (SoundPlayCtrl.Playing < SND_TOTAL_NUM))
                                {
                                    if (SndAttributeTable[SoundPlayCtrl.Playing].Mode == SND_MODE_SINGLE)
                                      Snd_PCM_Track_Play(SndAttributeTable[SoundPlayCtrl.Playing].Index, 0);
                                    else
                                      Snd_PCM_Track_Repeat_Play(SndAttributeTable[SoundPlayCtrl.Playing].Index, 0);
                                    
                                    SoundPlayCtrl.Timer = (SndAttributeTable[SoundPlayCtrl.Playing].Period + 9) / 10;
                                    if (SoundPlayCtrl.Cycle != SND_CYCLE_NONSTOP)
                                      SoundPlayCtrl.Cycle--;
                                    
                                    SoundPlayCtrl.Status = SND_PLAYER_PLAYING; 
                                }
                                else
                                {
              
                                  SoundPlayCtrl.Playing = SND_SRC_NONE;
                                  SoundPlayCtrl.Cycle   = 0;
                                  SoundPlayCtrl.Status  = SND_PLAYER_IDLE;           //取消播放请求
                                }
                                break;
    
    case SND_PLAYER_PLAYING   : if (SoundPlayCtrl.Timer)
                                  SoundPlayCtrl.Timer--;
                                
                                if (SoundPlayCtrl.Timer == 0)
                                {
                                  if (SoundPlayCtrl.Cycle == 0)
                                  {
                                    if (SndAttributeTable[SoundPlayCtrl.Playing].Mode != SND_MODE_SINGLE)
                                      Snd_PCM_Track_Stop_Play(0);
                  
                                    SoundPlayCtrl.Playing = SND_SRC_NONE;
                                    SoundPlayCtrl.Status  = SND_PLAYER_IDLE;
                                  }
                                  else
                                  {
                                    if (SndAttributeTable[SoundPlayCtrl.Playing].Mode == SND_MODE_SINGLE)
                                      Snd_PCM_Track_Play(SndAttributeTable[SoundPlayCtrl.Playing].Index, 0);
                                    
                                    SoundPlayCtrl.Timer = (SndAttributeTable[SoundPlayCtrl.Playing].Period + 9) / 10;
                                    if (SoundPlayCtrl.Cycle != SND_CYCLE_NONSTOP)
                                      SoundPlayCtrl.Cycle--;
                                  }
                                }
                                break;
                                
    case SND_PLAYER_STOP_REQ  : if (SoundPlayCtrl.Playing < SND_TOTAL_NUM)
                                {
                                  if (SndAttributeTable[SoundPlayCtrl.Playing].Mode != SND_MODE_SINGLE)
                                  {
                                    Snd_PCM_Track_Stop_Play(0);
                                                   
                                    SoundPlayCtrl.Playing = SND_SRC_NONE;
                                    SoundPlayCtrl.Cycle   = 0;
                                    SoundPlayCtrl.Status  = SND_PLAYER_IDLE;
                                  }
                                  else
                                  {
                                    if (SoundPlayCtrl.Timer)
                                      SoundPlayCtrl.Timer--;
                                
                                    if (SoundPlayCtrl.Timer == 0)
                                    {
                     
                                      SoundPlayCtrl.Playing = SND_SRC_NONE;
                                      SoundPlayCtrl.Cycle   = 0;
                                      SoundPlayCtrl.Status  = SND_PLAYER_IDLE;
                                    }
                                  }
                                }
                                break;
  }
}