/*
 * Copyright 2021 MindMotion Microelectronics Co., Ltd.
 * All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include "board_init.h"
#include "mp3_decode.h"
#include "ff.h"

/*
 * Macros.
 */



/*
 * Variables.
 */
/* for fs. */
     FATFS app_fs;
      DIR  app_fs_dir;
   FILINFO app_fs_fileinfo;
      char app_fs_filepath[16]; /* max len of full file path. */
const char app_fs_dirpath[] = "1:/";

/* for mp3. */
extern const mp3_decode_if_t  mp3_dec_if;
             mp3_decode_obj_t app_mp3_dec_obj;

/*
 * Declerations.
 */

bool app_fs_play_mp3_file(char *filepath);
/*
 * Functions.
 */
int main(void)
{
    BOARD_Init();

    printf("audio_fatfs_i2s_mp3_player_basic example.\r\n");

    printf("press any key to continue ...\r\n");
    getchar();

    /* mount sd card. */
    if (FR_OK == f_mount(&app_fs, app_fs_dirpath, 1))
    {
        printf("init sd card ok.\r\n");
    }
    else
    {
        printf("cannot mount sd card!\r\n");
        return false;
    }
    
    /* prepare the mp3 decoder. */
    mp3_decode_init(&app_mp3_dec_obj, (mp3_decode_if_t*)&mp3_dec_if);
    
    while (1)
    {
        /* travel the root dir of file system from sd card. */
        if (FR_OK == f_opendir(&app_fs_dir, app_fs_dirpath) )
        {
            while ( FR_OK == f_readdir(&app_fs_dir, &app_fs_fileinfo) )
            {
                /* skip the dirpath. */
                if (0 != (app_fs_fileinfo.fattrib & AM_DIR) ) /* find a dir. */
                {
                    continue;
                }

                /* recycle when reaching to the end of the filelist. */
                if (app_fs_fileinfo.fname[0] == '\0')
                {
                    printf("loop done.\r\n");
                    printf("press any key for next loop.\r\n");
                    getchar();
                    break;
                }

                /* match the .wav file. */
                if (   (strstr(app_fs_fileinfo.fname, ".mp3"))
                    || (strstr(app_fs_fileinfo.fname, ".MP3")) )
                {
                    memset(app_fs_filepath, 0, strlen(app_fs_filepath));
                    sprintf(app_fs_filepath, "%s%s", app_fs_dirpath, app_fs_fileinfo.fname);
                    printf("playing %s ... ?[y/n]\r\n", app_fs_filepath);

                    if (getchar() != 'y')
                    {
                        continue;
                    }
                    
                    /* play the wav file. */
                    if ( !app_fs_play_mp3_file(app_fs_filepath) )
                    {
                        printf("app_fs_play_wav_file() fail.\r\n");
                    }
                    else
                    {
                        printf("app_fs_play_wav_file() done.\r\n");
                    }

                }
            }
        }
    }
}


#define APP_PCM_BUF_LEN         (MP3_DECODE_FRAME_SAMPLES * 4)
#define APP_PCM_BUF_SIZE        (APP_PCM_BUF_LEN * sizeof(int16_t))
#define APP_PCM_BUF_HALF_LEN    (APP_PCM_BUF_LEN / 2)

int16_t pcm_buf[APP_PCM_BUF_LEN];

bool app_fs_play_mp3_file(char *filepath)
{
    /* open a mp3 file. */
    mp3_decode_open(&app_mp3_dec_obj, filepath);

    /* fill the pcm buf. */
    mp3_decode(&app_mp3_dec_obj, pcm_buf, APP_PCM_BUF_LEN);

    /* init audio. */
    Audio_ClearStatus(AUDIO_STATUS_XFER_HALF | AUDIO_STATUS_XFER_DONE);
    Audio_Setup(mp3_decode_get_sample_rate(&app_mp3_dec_obj), (uint16_t*)pcm_buf, APP_PCM_BUF_LEN);

    /* play. */
    Audio_Enable(true);
    
    /* ping-pang buffer. */
    while (1)
    {
        uint32_t audio_flags = Audio_GetStatus();
        if (0 != (audio_flags & AUDIO_STATUS_XFER_HALF) )
        {
            /* fill the first half pcm buf. */
            if (0 == mp3_decode(&app_mp3_dec_obj, &pcm_buf[0], APP_PCM_BUF_HALF_LEN) )
            {
                /* mp3 play done. */
                break;
            }
            Audio_ClearStatus(AUDIO_STATUS_XFER_HALF);
        }
        else if (0 != (audio_flags & AUDIO_STATUS_XFER_DONE) )
        {
            /* fill the sencond half pcm buf. */
            if (0 == mp3_decode(&app_mp3_dec_obj, &pcm_buf[APP_PCM_BUF_HALF_LEN], APP_PCM_BUF_HALF_LEN) )
            {
                /* mp3 play done. */
                break;
            }
            Audio_ClearStatus(AUDIO_STATUS_XFER_DONE);
        }
        else
        {
            /* dummy loop. */
        }
    }
    /* close the audio. */
    Audio_Enable(false);
    return true;
}


/* EOF. */
