#include <windows.h>

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

#include "kbdmusic_module.h"
#include "kbdmusic_player.h"

#ifdef _DEBUG
static const DWORD kbdmusic_Version = 0x7FFFFFFF; //デバッグ時は優先度最大
#define KBDMUSIC_VERSION_STR L"0x7FFFFFFF(Debug)"
#else
static const DWORD kbdmusic_Version = 5;
#define KBDMUSIC_VERSION_STR L"0.05"
#endif
///////////////////////////////////////////////////////////////////////////////
// {B6F740CF-E3F3-4A91-B8DA-53D3E63346CE}
static const GUID kbdmusic_GUID = 
{ 0xb6f740cf, 0xe3f3, 0x4a91, { 0xb8, 0xda, 0x53, 0xd3, 0xe6, 0x33, 0x46, 0xce } };

static const wchar_t kbdmusic_Description[] = L"DirectMusic Player v" KBDMUSIC_VERSION_STR ;
static const wchar_t kbdmusic_Copyright[] =  L"Copyright(C) 2016-2019 Kobarin";
static const wchar_t kbdmusic_MultipleInstance = KPI_MULTINST_INFINITE;
static const DWORD kbdmusic_SupportTagInfo = 0;
static const DWORD kbdmusic_SupportConfig =  1;
static const wchar_t kbdmusic_SupportExts[] = L".sgt/.sgp/.mid";
static const wchar_t kbdmusic_MultiSongExts[] = L"";
static const wchar_t kbdmusic_SupportCodecs[] = L"";
static const wchar_t kbdmusic_SupportContainers[] = L"";
static void* kbdmusic_Reserved1 = NULL;
static void* kbdmusic_Reserved2 = NULL;
///////////////////////////////////////////////////////////////////////////////
KbDMusicPlayerModule::KbDMusicPlayerModule(IKpiConfig *pConfig)
    :m_ModuleInfo{
        sizeof(KPI_PLAYER_MODULEINFO),
        KPI_PLAYER_MODULE_VERSION,
        kbdmusic_Version,
        kbdmusic_MultipleInstance,
        kbdmusic_GUID,
        kbdmusic_Description,
        kbdmusic_Copyright,
        kbdmusic_SupportExts,
        kbdmusic_MultiSongExts,
        kbdmusic_Reserved1,
        kbdmusic_Reserved2,
        kbdmusic_SupportTagInfo,
        kbdmusic_SupportConfig,
        0,0,0,0}
{
    m_pConfig = pConfig;
    pConfig->AddRef();
}
///////////////////////////////////////////////////////////////////////////////
KbDMusicPlayerModule::~KbDMusicPlayerModule(void)
{
    m_pConfig->Release();
}
///////////////////////////////////////////////////////////////////////////////
void WINAPI KbDMusicPlayerModule::GetModuleInfo(const KPI_PLAYER_MODULEINFO **ppInfo)
{
    *ppInfo = &m_ModuleInfo;
}
///////////////////////////////////////////////////////////////////////////////
DWORD WINAPI KbDMusicPlayerModule::Open(const KPI_MEDIAINFO *cpRequest, 
                                        IKpiFile   *pFile,
                                        IKpiFolder *pFolder,
                                        IKpiPlayer **ppPlayer)
{
    KbDMusicPlayer *pPlayer = new KbDMusicPlayer(m_pConfig);
    DWORD dwRet = pPlayer->Open(pFile, pFolder);
    if(dwRet == 0){
        pPlayer->Release();
        *ppPlayer = NULL;
    }
    else{
        *ppPlayer = pPlayer;
    }
    return dwRet;
}
///////////////////////////////////////////////////////////////////////////////
BOOL  WINAPI KbDMusicPlayerModule::EnumConfig(IKpiConfigEnumerator *pEnumerator)
{
    KPI_CFG_KEY key[] = {
    //   type, section, key, keydesc, default, min, max, list, listdesc, help
        {KPI_CFG_TYPE_FOLDER, L"General", L"DlsPath", L"DLS の検索パス", 
            L"", NULL, L"1024", //default, min, max
            NULL, //list
            NULL, //listdesc
            L"DLS ファイルの検索パスを指定します。サブフォルダを検索しないため、\r\n"
            L"指定フォルダの直下に全ての DLS ファイルを置く必要があります。"},//help
        {0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}
    };
    for(int i = 0; key[i].cszSection; i++){
        pEnumerator->EnumKey(&key[i]);
    }
    return TRUE;
}
//////////////////////////////////////////////////////////////////////////////
DWORD WINAPI KbDMusicPlayerModule::ApplyConfig(const wchar_t *cszSection, //セクション名
                                               const wchar_t *cszKey,     //キー名
                                               INT64 nValue,
                                               double dValue,
                                               const wchar_t *cszValue)     
{
    m_pConfig->SetStr(cszSection, cszKey, cszValue);
    return KPI_CFGRET_RELOAD_DATA;
}
///////////////////////////////////////////////////////////////////////////////
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, &kbdmusic_GUID, NULL, &pConfig);
    IKpiPlayerModule *pPlayerModule = new KbDMusicPlayerModule(pConfig);
    *ppvObject = pPlayerModule;
    pConfig->Release();
    return S_OK;
}
/////////////////////////////////////////////////////////////////////////////
//DllMain
//////////////////////////////////////////////////////////////////////////////
BOOL APIENTRY DllMain( HMODULE 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;
}

