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

#include "kbtta_decoder.h"

using namespace tta;

//TTAint32(CALLBACK *read)(struct _tag_TTA_io_callback *, TTAuint8 *, TTAuint32);
//TTAint32(CALLBACK *write)(struct _tag_TTA_io_callback *, TTAuint8 *, TTAuint32);
//TTAint64(CALLBACK *seek)(struct _tag_TTA_io_callback *, TTAint64 offset);
//////////////////////////////////////////////////////////////////////////////
/*
TTAint32 CALLBACK tta_io_read(TTA_io_callback *io_callback, TTAuint8 *buffer, TTAuint32 size)
{
    IKpiFile *pFile =  ((TTA_io_callback2*)io_callback)->pFile;
    return pFile->Read(buffer, size);
}
//////////////////////////////////////////////////////////////////////////////
TTAint32 CALLBACK tta_io_write(TTA_io_callback *, TTAuint8 *, TTAuint32)
{
    return 0;
}
//////////////////////////////////////////////////////////////////////////////
TTAint64 CALLBACK tta_io_seek(TTA_io_callback *io_callback, TTAint64 offset)
{
    IKpiFile *pFile =  ((TTA_io_callback2*)io_callback)->pFile;
    return pFile->Seek(offset, FILE_BEGIN);
}*/
//////////////////////////////////////////////////////////////////////////////
KbTtaDecoder::KbTtaDecoder(void)
{
    kpi_InitMediaInfo(&m_MediaInfo);
    ZeroMemory(&m_ttaInfo, sizeof(m_ttaInfo));
    m_io_callback.read = &TTA_io_callback2::tta_io_read;
    m_io_callback.write = &TTA_io_callback2::tta_io_write;
    m_io_callback.seek = &TTA_io_callback2::tta_io_seek;
    m_io_callback.pFile = NULL;
}
//////////////////////////////////////////////////////////////////////////////
KbTtaDecoder::~KbTtaDecoder(void)
{
    delete m_ttaDecoder;
    if(m_io_callback.pFile){
        m_io_callback.pFile->Release();
    }
}
//////////////////////////////////////////////////////////////////////////////
DWORD __fastcall KbTtaDecoder::Open(const KPI_MEDIAINFO *cpRequest, 
                                    IKpiFile *pFile, 
                                    IKpiFolder *pFolder)
{
    m_io_callback.pFile = pFile;
    pFile->AddRef();
    try{
        m_ttaDecoder = new tta_decoder(&m_io_callback);
        m_ttaDecoder->init_get_info(&m_ttaInfo, 0);
    }
    catch(...){
        return 0;
    }
    m_MediaInfo.dwSampleRate = m_ttaInfo.sps;
    m_MediaInfo.dwChannels = m_ttaInfo.nch;
    m_MediaInfo.nBitsPerSample = m_ttaInfo.bps;
    m_MediaInfo.qwLength = kpi_SampleTo100ns(m_ttaInfo.samples, m_ttaInfo.sps);
    m_MediaInfo.dwSeekableFlags = KPI_MEDIAINFO::SEEK_FLAGS_SAMPLE;
    m_MediaInfo.dwUnitSample = 0;
    m_MediaInfo.dwNumber = 1;
    m_MediaInfo.dwCount = 1;
    return TRUE;
}
//////////////////////////////////////////////////////////////////////////////
DWORD WINAPI KbTtaDecoder::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;
}
//////////////////////////////////////////////////////////////////////////////
DWORD WINAPI KbTtaDecoder::Render(BYTE *Buffer, DWORD dwSizeSample)
{
    DWORD dwBlockAlign = (m_MediaInfo.nBitsPerSample / 8) * m_MediaInfo.dwChannels;
    int nRet = 0;
    try{
        nRet = m_ttaDecoder->process_stream((TTAuint8*)Buffer, dwSizeSample * dwBlockAlign);
    }
    catch(...){
    }
    return nRet;
}
//////////////////////////////////////////////////////////////////////////////
UINT64 WINAPI KbTtaDecoder::Seek(UINT64 qwPosSample, DWORD dwFlags)
{
    UINT64 qwPos100ns = kpi_SampleTo100ns(qwPosSample, m_MediaInfo.dwSampleRate);
    TTAuint32 pos_sec = qwPos100ns / (1000*10000);
    TTAuint64 ret_sample;
    try{
        m_ttaDecoder->set_position(pos_sec, &ret_sample);
    }
    catch(...){
        try{
            m_ttaDecoder->set_position(0, &ret_sample);
        }
        catch(...){
            ret_sample = 0;
        }
    }
    return ret_sample;
}
//////////////////////////////////////////////////////////////////////////////
