#include <windows.h>
#include <stdio.h>

#include "kbemidi_decoder.h"
#include "kbemidi_config.h"
#include "CSMFPlay.hpp"
//////////////////////////////////////////////////////////////////////////////
KbEMidiDecoder::KbEMidiDecoder(IKpiConfig *pConfig)
{
    kpi_InitMediaInfo(&m_MediaInfo);
    m_smfplay = NULL;
    m_qwCurSample = 0;
    m_pConfig = pConfig;
    pConfig->AddRef();
}
//////////////////////////////////////////////////////////////////////////////
KbEMidiDecoder::~KbEMidiDecoder(void)
{
    delete m_smfplay;
    m_pConfig->Release();
}
//////////////////////////////////////////////////////////////////////////////
DWORD __fastcall KbEMidiDecoder::Open(const KPI_MEDIAINFO *cpRequest,
                                   IKpiFile   *pFile,
                                   IKpiFolder *pFolder)
{
    const DWORD RATE_MAX = 48000;//48000Hz を超えるとドラムパートがきちんと鳴らなくなる？
    kbemidi_Settings settings;
    kbemidi_GetSettings(m_pConfig, &settings);
    UINT64 qwSize = pFile->GetSize();
    if(qwSize > 128 * 1024 * 1024){//サイズが大きすぎ
        return 0;
    }
    DWORD dwSampleRate = cpRequest->dwSampleRate;
    if(dwSampleRate == 0){
        dwSampleRate = 44100;
    }
    else if(dwSampleRate < 8000){
        dwSampleRate = 8000;
    }
    else if(dwSampleRate > RATE_MAX){
        dwSampleRate = RATE_MAX;
    }
    m_smfplay = new dsa::CSMFPlay(dwSampleRate,
                                  settings.bEnableOPLL,
                                  settings.bEnableSCC,
                                  settings.bEnablePSGDrum, 
                                  settings.nNumDevices*2,
                                  settings.nNumThreads);
    BYTE *pBuf = (BYTE*)malloc((size_t)qwSize);
    qwSize = pFile->Read(pBuf, (DWORD)qwSize);
    if(!m_smfplay->Open(pBuf, (DWORD)qwSize)){
        free(pBuf);
        delete m_smfplay;
        return 0;
    }
    free(pBuf);
    m_MediaInfo.dwSampleRate = dwSampleRate;
    m_MediaInfo.dwChannels = 2;
    m_MediaInfo.nBitsPerSample = -64;
    m_MediaInfo.dwSeekableFlags =KPI_MEDIAINFO::SEEK_FLAGS_SAMPLE;
    m_MediaInfo.dwUnitSample = 0;//
    m_MediaInfo.qwLength = m_smfplay->GetDuration() * 10000000ui64;
    m_MediaInfo.qwLoop = m_smfplay->IsLoopMIDI() ? (UINT64)-1 : 0;
    m_MediaInfo.dwCount = 1;
    m_MediaInfo.dwNumber = 1;
    return 1; 
}
///////////////////////////////////////////////////////////////////////////
DWORD WINAPI KbEMidiDecoder::Render(BYTE *pBuffer, DWORD dwSizeSample)
{
    DWORD dwRet = m_smfplay->Render((double*)pBuffer, dwSizeSample);
    m_qwCurSample += dwRet;
    return dwRet;
}
///////////////////////////////////////////////////////////////////////////
UINT64 WINAPI KbEMidiDecoder::Seek(UINT64 qwPosSample, DWORD dwFlag)
{
    kbemidi_Settings settings;
    kbemidi_GetSettings(m_pConfig, &settings);
    if(!settings.bFastSeek){//先頭に戻す
        m_smfplay->Start();
        m_qwCurSample = 0;
        return 0;
    }
    if(m_qwCurSample >= qwPosSample){//先頭に戻してから
        m_smfplay->Start();
        m_qwCurSample = 0;
    }
    else{
        qwPosSample -= m_qwCurSample;
    }
    Render(NULL, qwPosSample);
    return m_qwCurSample;
}
///////////////////////////////////////////////////////////////////////////
DWORD WINAPI KbEMidiDecoder::Select(DWORD dwNumber,
                                  const KPI_MEDIAINFO **ppMediaInfo,
                                  IKpiTagInfo *pTagInfo,
                                  DWORD dwTagGetFlags)
{
    if(ppMediaInfo){
        *ppMediaInfo = NULL;
    }
    if (dwNumber > m_MediaInfo.dwCount) {
        return 0;
    }
    if (!ppMediaInfo) {//タグ取得のみ(タイトル/アーティストのみ)
        return 1;
    }
    *ppMediaInfo = &m_MediaInfo;
    return 1;
}
/////////////////////////////////////////////////////////////////////////
