#include <windows.h>
#include <wchar.h>

#ifdef _DEBUG
#define LEAK_CHECK //メモリリーク検出（しない場合はコメントアウト）
#endif
#ifdef LEAK_CHECK
#include <crtdbg.h>
#endif

#include "OptimFROG/PortableTypes.h"
#include "OptimFROG/OptimFROG.h"
#include "kbofr_module.h"
#include "kbofr_decoder.h"

#ifdef _DEBUG
static const DWORD kbofr_Version = 0x7FFFFFFF; //デバッグ時は優先度最大
#define KBOFR_VERSION_STR L"0x7FFFFFFF(Debug)"
#else
static const DWORD kbofr_Version = 11; //プラグインのバージョン
#define KBOFR_VERSION_STR  L"0.11"
#endif
//////////////////////////////////////////////////////////////////////////////
// {4E3E9A78-0A10-4EAC-A948-A343579DAEFC}
static const GUID kbofr_GUID = 
{ 0x4e3e9a78, 0xa10, 0x4eac, { 0xa9, 0x48, 0xa3, 0x43, 0x57, 0x9d, 0xae, 0xfc } };
//////////////////////////////////////////////////////////////////////////////
static const wchar_t kbofr_Description[] = L"OptimFROG Decoder v" KBOFR_VERSION_STR " based on OptimFROG.dll %s";
static const wchar_t kbofr_Copyright[] = L"kbofr.kpi Copyright (C) 2004-2019 Kobarin\n"
                                         L"OptimFROG.dll Copyright (C) 1996-2016 Florin Ghido";
static const wchar_t kbofr_SupportExts[] = L".ofr/.ofs";
static const wchar_t kbofr_MultiSongExts[] = L"";
static const DWORD kbofr_SuportTagInfo = KPI_DECODER_MODULEINFO::TAG_EXTRA;
static const DWORD kbofr_SuportConfig = 0;
static void* kbofr_Reserved1 = NULL;
static void* kbofr_Reserved2 = NULL;
//////////////////////////////////////////////////////////////////////////////
KbOfrDecoderModule::KbOfrDecoderModule(void)
    :m_ModuleInfo{
        sizeof(KPI_DECODER_MODULEINFO), //cb(=sizeof(KPI_DECODER_MODULEINFO))
        KPI_DECODER_MODULE_VERSION,     //dwModuleVersion(=KPI_DECODER_MODULE_VERSION)
        kbofr_Version,                  //dwPluginVersion
        KPI_MULTINST_INFINITE, //dwMultipleInstance
        kbofr_GUID,
        kbofr_Description,
        kbofr_Copyright,
        kbofr_SupportExts,
        kbofr_MultiSongExts,
        kbofr_Reserved1,
        kbofr_Reserved2,
        kbofr_SuportTagInfo,
        kbofr_SuportConfig,
        0, 0, 0, 0                      //reserved
     }
{
    uInt32_t ver = OptimFROG_getVersion();
    wchar_t szVersion[32];
    _snwprintf_s(szVersion, _TRUNCATE, L"v%d.%03d", ver / 1000, ver % 1000);
    _snwprintf_s(m_szDescription, _TRUNCATE, kbofr_Description, szVersion);
    m_ModuleInfo.cszDescription = m_szDescription;
}
//////////////////////////////////////////////////////////////////////////////
KbOfrDecoderModule::~KbOfrDecoderModule(void)
{
}
//////////////////////////////////////////////////////////////////////////////
void  WINAPI KbOfrDecoderModule::GetModuleInfo(const KPI_DECODER_MODULEINFO **ppInfo)
{
    *ppInfo = &m_ModuleInfo;
}
//////////////////////////////////////////////////////////////////////////////
DWORD WINAPI KbOfrDecoderModule::Open(const KPI_MEDIAINFO *cpRequest,
    IKpiFile     *pFile,   //音楽データ
    IKpiFolder   *pFolder, //音楽データがあるフォルダ
    IKpiDecoder **ppDecoder)
{
    KbOfrDecoder *pDecoder = new KbOfrDecoder;
    DWORD dwCount = pDecoder->Open(cpRequest, pFile, pFolder);
    if(dwCount == 0){
        *ppDecoder = NULL;
        delete pDecoder;
        return 0;
    }
    *ppDecoder = pDecoder;
    return dwCount;
}
/////////////////////////////////////////////////////////////////////////////
HRESULT WINAPI kpi_CreateInstance(REFIID riid, void **ppvObject, IKpiUnknown *pUnknown)
{
    *ppvObject = NULL;
    if(!IsEqualIID(riid, IID_IKpiDecoderModule)){
        return E_NOINTERFACE;
    }
    IKpiDecoderModule *pDecoderModule = new KbOfrDecoderModule();
    *ppvObject = pDecoderModule;
    return S_OK;
}
/////////////////////////////////////////////////////////////////////////////
//DllMain
/////////////////////////////////////////////////////////////////////////////
BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
    switch (ul_reason_for_call) {
    case DLL_PROCESS_ATTACH:
    {
#ifdef LEAK_CHECK
        //メモリリーク検出
        int tmpDbgFlag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
        //tmpDbgFlag |= _CRTDBG_DELAY_FREE_MEM_DF;
        tmpDbgFlag |= _CRTDBG_LEAK_CHECK_DF;
        //tmpDbgFlag |= _CRTDBG_CHECK_ALWAYS_DF;
        _CrtSetDbgFlag(tmpDbgFlag);
#endif
        DisableThreadLibraryCalls(hModule);
        break;
    }
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
