#include <windows.h>

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

#include "kbfmp7_module.h"
#include "kbfmp7_player.h"
#include "kbfmp7_config.h"

///////////////////////////////////////////////////////////////////////////////
#ifdef _DEBUG
static const DWORD kbfmp7_Version = 0x7FFFFFFF; //デバッグ時は優先度最大
#define KBFMP7_VERSION_STR L"0x7FFFFFFF(Debug)"
#else
static const DWORD kbfmp7_Version = 3;
#define KBFMP7_VERSION_STR L"0.03"
#endif
// {794768A2-FBA6-41AF-982A-940EA657840A}
static const GUID kbfmp7_GUID =
{ 0x794768a2, 0xfba6, 0x41af, { 0x98, 0x2a, 0x94, 0xe, 0xa6, 0x57, 0x84, 0xa } };

static const wchar_t kbfmp7_Description[] = L"FMP7 Player v" KBFMP7_VERSION_STR " based on FMP7 ver7.10g";
static const wchar_t kbfmp7_Copyright[] = L"kbfmp7.kpi Copyright(C) 2024 Kobarin\n"
                                          L"FMP7.exe Copyright(C) 2010-2015 Guu";
static const DWORD kbfmp7_MultipleInstance = //KPI_MULTINST_INFINITE;//実際はシステムに１つだけだが演奏が止まっても再生中に曲長計算が出来た方がマシなので
                                             KPI_MULTINST_ONE;//
                                             //KPI_MULTINST_UNIQUE;
static const DWORD kbfmp7_SupportTagInfo = KPI_DECODER_MODULEINFO::TAG_TITLE;
static const DWORD kbfmp7_SupportConfig = 1;

static const wchar_t kbfmp7_SupportExts[] = L".owi";
static const wchar_t kbfmp7_MultiSongExts[] = L"";
static void* kbfmp7_Reserved1 = NULL;
static void* kbfmp7_Reserved2 = NULL;

///////////////////////////////////////////////////////////////////////////////
KbFmp7PlayerModule::KbFmp7PlayerModule(IKpiConfig *pConfig)
    :m_ModuleInfo{
        sizeof(KPI_PLAYER_MODULEINFO),
        KPI_PLAYER_MODULE_VERSION,
        kbfmp7_Version,
        kbfmp7_MultipleInstance,
        kbfmp7_GUID,
        kbfmp7_Description,
        kbfmp7_Copyright,
        kbfmp7_SupportExts,
        kbfmp7_MultiSongExts,
        kbfmp7_Reserved1,
        kbfmp7_Reserved2,
        kbfmp7_SupportTagInfo,
        kbfmp7_SupportConfig,
        0,0,0,0}
{
    m_pConfig = pConfig;
    pConfig->AddRef();
}
///////////////////////////////////////////////////////////////////////////////
KbFmp7PlayerModule::~KbFmp7PlayerModule(void)
{
    KbFmp7Player::Uinitialize(m_pConfig);
    m_pConfig->Release();
}
///////////////////////////////////////////////////////////////////////////////
void WINAPI KbFmp7PlayerModule::GetModuleInfo(const KPI_PLAYER_MODULEINFO **ppInfo)
{
    *ppInfo = &m_ModuleInfo;
}
///////////////////////////////////////////////////////////////////////////////
DWORD WINAPI KbFmp7PlayerModule::Open(const KPI_MEDIAINFO* cpRequest,
    IKpiFile* pFile,
    IKpiFolder* pFolder,
    IKpiPlayer** ppPlayer)
{
    KbFmp7Player *pPlayer = new KbFmp7Player(m_pConfig);
    DWORD dwCount = pPlayer->Open(cpRequest, pFile, pFolder);
    if(dwCount == 0){
        pPlayer->Release();
        return 0;
    }
    *ppPlayer = pPlayer;
    return dwCount;
}
///////////////////////////////////////////////////////////////////////////////
BOOL  WINAPI KbFmp7PlayerModule::EnumConfig(IKpiConfigEnumerator *pEnumerator)
{
    return kbfmp7_EnumConfig(m_pConfig, pEnumerator);
}
//////////////////////////////////////////////////////////////////////////////
DWORD WINAPI KbFmp7PlayerModule::ApplyConfig(const wchar_t *cszSection, //セクション名
                                            const wchar_t *cszKey,     //キー名
                                            INT64 nValue,
                                            double dValue,
                                            const wchar_t *cszValue)     
{
    return kbfmp7_ApplyConfig(m_pConfig, cszSection, cszKey, nValue, dValue, cszValue);
}
///////////////////////////////////////////////////////////////////////////////
HRESULT WINAPI kpi_CreateInstance(REFIID riid, void **ppvObject, IKpiUnknown *pUnknown)
{
    *ppvObject = NULL;
    if(!IsEqualIID(riid, IID_IKpiPlayerModule)){
        return E_NOINTERFACE;
    }
    IKpiConfig *pConfig = NULL;
    kpi_CreateConfig(pUnknown, &kbfmp7_GUID, NULL, &pConfig);
    IKpiPlayerModule *pPlayerModule = new KbFmp7PlayerModule(pConfig);
    *ppvObject = pPlayerModule;
    pConfig->Release();//KbFmp7PlayerModule 内で AddRef しているので必ず必要
    return S_OK;
}
/////////////////////////////////////////////////////////////////////////////
//DllMain
/////////////////////////////////////////////////////////////////////////////
BOOL WINAPI DllMain(HINSTANCE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
    switch (ul_reason_for_call) {
    case DLL_PROCESS_ATTACH: {
        DisableThreadLibraryCalls(hModule);
#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
        break;
    }
    case DLL_PROCESS_DETACH: {
        break;
    }
    }
    return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
