#include <windows.h>

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

#ifdef _DEBUG
static const DWORD kbvgm_Version = 0x7FFFFFFF; //デバッグ時は優先度最大
#define kbvgm_VERSION_STR L"0x7FFFFFFF(Debug)"
#else
static const DWORD kbvgm_Version = 16;
#define kbvgm_VERSION_STR L"0.16"
#endif

static const wchar_t kbvgm_Description[] = L"VGM Decoder v" kbvgm_VERSION_STR L" based on libvgm v0.51.1(2024/06/07)" ;
static const wchar_t kbvgm_Copyright[] =   L"kbvgm.kpi Copyright (C) 2021-2024 Kobarin\n"
                                           L"libvgm Copyright (C) Valley Bell";

// {2162C179-7F72-429F-B64F-F5ABE2AD7B8E}
static const GUID kbvgm_GUID =
{ 0x2162c179, 0x7f72, 0x429f, { 0xb6, 0x4f, 0xf5, 0xab, 0xe2, 0xad, 0x7b, 0x8e } };


static const DWORD kbvgm_MultipleInstance = KPI_MULTINST_INFINITE;//同時に何個でも作成可能
                                            //KPI_MULTINST_ZERO;  //常に別プロセス起動
                                            //KPI_MULTINST_ONE;   //2個目以降は別プロセス起動
                                            //KPI_MULTINST_UNIQUE;//プロセスをまたいでも１つまで
                                            //KPI_MULTINST_ZERO + N;//(N+1)個目以降は別プロセス起動
                                            //↑どれか１つを選択
static const wchar_t kbvgm_SupportExts[] = L".vgm/.vgz/.s98/.gym/.dro/.cym/.mym/.x1f";
static const wchar_t kbvgm_MultiSongExts[] = L"";
static const DWORD kbvgm_SupportTagInfo = KPI_DECODER_MODULEINFO::TAG_TITLE | //未対応ならコメントアウト
                                            //KPI_DECODER_MODULEINFO::TAG_EXTRA | //未対応ならコメントアウト
                                             0;
static const DWORD kbvgm_SupportConfig = 1;
static void* kbvgm_Reserved1 = NULL;
static void* kbvgm_Reserved2 = NULL;
//////////////////////////////////////////////////////////////////////////////
KbVgmDecoderModule::KbVgmDecoderModule(IKpiConfig *pConfig)
    :m_ModuleInfo{
        sizeof(KPI_DECODER_MODULEINFO), //cb(=sizeof(KPI_DECODER_MODULEINFO))
        KPI_DECODER_MODULE_VERSION,     //dwModuleVersion(=KPI_DECODER_MODULE_VERSION)
        kbvgm_Version,
        kbvgm_MultipleInstance,
        kbvgm_GUID,
        kbvgm_Description,
        kbvgm_Copyright,
        kbvgm_SupportExts,
        kbvgm_MultiSongExts,
        kbvgm_Reserved1,
        kbvgm_Reserved2,
        kbvgm_SupportTagInfo,
        kbvgm_SupportConfig,
        0, 0, 0, 0                      //reserved
     }
{
    m_pConfig = pConfig;
    pConfig->AddRef();
}
//////////////////////////////////////////////////////////////////////////////
KbVgmDecoderModule::~KbVgmDecoderModule(void)
{
    m_pConfig->Release();
}
//////////////////////////////////////////////////////////////////////////////
void  WINAPI KbVgmDecoderModule::GetModuleInfo(const KPI_DECODER_MODULEINFO **ppInfo)
{
    *ppInfo = &m_ModuleInfo;
}
//////////////////////////////////////////////////////////////////////////////
DWORD WINAPI KbVgmDecoderModule::Open(const KPI_MEDIAINFO *cpRequest,
    IKpiFile     *pFile,   //音楽データ
    IKpiFolder   *pFolder, //音楽データがあるフォルダ
    IKpiDecoder **ppDecoder)
{
    KbVgmDecoder *pDecoder = new KbVgmDecoder;
    DWORD dwRet = pDecoder->Open(cpRequest, m_pConfig, pFile, pFolder);
    if(dwRet != 0){
        *ppDecoder = pDecoder;
        return dwRet;
    }
    pDecoder->Release();
    return 0;
}
/////////////////////////////////////////////////////////////////////////////
BOOL  WINAPI KbVgmDecoderModule::EnumConfig(IKpiConfigEnumerator *pEnumerator)
{ 
    return kbvgm_EnumConfig(m_pConfig, pEnumerator); 
}
/////////////////////////////////////////////////////////////////////////////
DWORD WINAPI KbVgmDecoderModule::ApplyConfig(const wchar_t *cszSection,//セクション名
    const wchar_t *cszKey,    //キー名
    INT64  nValue, //変更後の値(BOOL/INT の場合)
    double dValue, //変更後の値(FLOAT の場合)
    const wchar_t *cszValue) 
{//変更後の値(文字列)
    return kbvgm_ApplyConfig(m_pConfig, cszSection, cszKey, nValue, dValue, cszValue);
}
/////////////////////////////////////////////////////////////////////////////
HRESULT WINAPI kpi_CreateInstance(REFIID riid, void **ppvObject, IKpiUnknown *pUnknown)
{
    *ppvObject = NULL;
    if(!IsEqualIID(riid, IID_IKpiDecoderModule)){
        return E_NOINTERFACE;
    }
    IKpiConfig *pConfig;
    kpi_CreateConfig(pUnknown, &kbvgm_GUID, NULL, &pConfig);
    IKpiDecoderModule *pDecoderModule = new KbVgmDecoderModule(pConfig);
    *ppvObject = pDecoderModule;
    pConfig->Release();
    return S_OK;
}
/////////////////////////////////////////////////////////////////////////////
//DllMain
/////////////////////////////////////////////////////////////////////////////
HINSTANCE g_hKpi = NULL;

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);
        //_crtBreakAlloc = 126;
#endif
        DisableThreadLibraryCalls(hModule);
        g_hKpi = hModule;
        break;
    }
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}
/////////////////////////////////////////////////////////////////////////////

