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

static const wchar_t SEC_GENERAL[] = L"General";
static const wchar_t KEY_SAMPLE_RATE[] = L"SampleRate";
static const wchar_t KEY_VOLUME[] = L"Volume";
static const wchar_t KEY_LOOP[] = L"Loop";
static const wchar_t KEY_INTRO_LOOP[] = L"IntroLoop";
static const wchar_t KEY_LOOP_RATIO[] = L"LoopRatio";
static const wchar_t KEY_LOOP_COUNT[] = L"LoopCount";
static const wchar_t KEY_FADEOUT[] = L"FadeOut";

static const int LOOP_DEFAULT = -1;
static const wchar_t SZ_LOOP_DEFAULT[] = L"-1";
static const DWORD SAMPLE_RATE_DEFAULT = 44100;
static const wchar_t SZ_SAMPLE_RATE_DEFAULT[] = L"44100";
static const double VOLUME_DEFAULT = 0.8;
static const wchar_t SZ_VOLUME_DEFAULT[] = L"0.8";
static const BOOL INTRO_LOOP_DEFAULT = FALSE;
static const wchar_t SZ_INTRO_LOOP_DEFAULT[] = L"0";
static const DWORD LOOP_RATIO_DEFAULT = 10;
static const wchar_t SZ_LOOP_RATIO_DEFAULT[] = L"10";
static const DWORD LOOP_COUNT_DEFAULT = 0;
static const wchar_t SZ_LOOP_COUNT_DEFAULT[] = L"0";
static const int FADEOUT_DEFAULT = -1;
static const wchar_t SZ_FADEOUT_DEFAULT[] = L"-1";

/////////////////////////////////////////////////////////////////////////////
BOOL __fastcall kbpxtone_EnumConfig(IKpiConfigEnumerator *pEnumerator)
{
    static const KPI_CFG_SECTION sec[] = {
        {SEC_GENERAL, NULL, L"kbpxtone.kpi に関する一般的な設定です。"},
        {NULL, NULL, NULL}
    };
    static const KPI_CFG_KEY key[] = {
    //   type, section, key, keydesc, default, min, max, list, listdesc, help
        {KPI_CFG_TYPE_INT, SEC_GENERAL, KEY_SAMPLE_RATE, L"再生周波数",
            SZ_SAMPLE_RATE_DEFAULT, NULL, NULL, //default/min/max
            L"44100\t48000\t88200\t96000\t176400\t192000\t-44100\t\-48000\t-88200\t-96000\t-176400\t-192000", //list
            L"44100Hz\t48000Hz\t88200Hz\t96000Hz\t176400Hz\t192000Hz\t44100Hz(要求を無視)\t48000Hz(要求を無視)\t88200Hz(要求を無視)\t96000Hz(要求を無視)\t176400Hz(要求を無視)\t192000Hz(要求を無視)", //listdesc
            L"本体からの要求が 0 の場合の再生周波数です。\r\n"
            L"\r\n"
            L"負の値を指定すると本体からの要求を無視します。\r\n"
            L""           
            },//help
        {KPI_CFG_TYPE_FLOAT, SEC_GENERAL, KEY_VOLUME, L"音量",
            SZ_VOLUME_DEFAULT, L"0.10", L"1.0", //default/min/max
            L"1.0\t0.9\t0.8\t0.7\t0.6\t0.5\t0.4\t0.3\t0.2\t0.1", //list
            L"100%\t90%\t80%\t70%\t60%\t50%\t40%\t30%\t20%\t10%", //listdesc
            L"音量を指定します。\r\n"
            L"音割れが気になる場合や、連続再生時に他のファイル形式と比べて\r\n"
            L"音量が大きいと感じる場合は 1.0 より小さくして下さい。\r\n"
            L""
            },//help
        {KPI_CFG_TYPE_INT, SEC_GENERAL, KEY_LOOP_COUNT, L"ループ回数",
            SZ_LOOP_COUNT_DEFAULT, L"0", L"10", //default/min/max
            L"0\t1\t2\t3\t4\t5\t6\t7\t8\t9\t10", //list
            L"本体の設定に従う\t1回\t2回\t3回\t4回\t5回\t6回\t7回\t8回\t9回\t10回", //listdesc
            L"ループ曲に対するループ回数を指定します。\r\n"
            L"0 を指定すると本体の「デフォルトのループ回数」に従います。\r\n"
            L"本体の「ループ回数を曲から取得」が無効の場合、この設定は\r\n"
            L"本体によって無視されます。\r\n"
            L"\r\n"
            L"この設定は連続再生時に有効です。無限ループさせたい場合は\r\n"
            L"本体側で「単曲リピート」を有効にして下さい。\r\n"
            L""
            },//help
        {KPI_CFG_TYPE_INT, SEC_GENERAL, KEY_FADEOUT, L"フェードアウト時間",
            SZ_FADEOUT_DEFAULT, L"-1", L"30000", //default/min/max
            L"-1\t0\t1000\t2000\t3000\t4000\t5000\t6000\t7000\t8000\t9000\t10000\t15000\t20000", //list
            L"本体の設定に従う\t0秒\t1秒\t2秒\t3秒\t4秒\t5秒\t6秒\t7秒\t8秒\t9秒\t10秒\t15秒\t20秒", //listdesc
            L"ループ曲に対するフェードアウト時間を指定します。\r\n"
            L"単位はミリ秒です。(1秒=1000ミリ秒)\r\n"
            L"-1 を指定すると本体の「デフォルトのフェード時間」に従います。\r\n"
            L"本体の「フェード時間を曲から取得」が無効の場合、この設定は\r\n"
            L"本体によって無視されます。\r\n"
            },//help
        {KPI_CFG_TYPE_INT, SEC_GENERAL, KEY_LOOP, L"ループ判別",
            SZ_LOOP_DEFAULT, NULL, NULL, //default/min/max
            L"-1\t0\t1", //list
            L"判別条件に従う\tループ曲と見なさない\tループ曲と見なす", //listdesc
            L"-1: 「イントロがない曲をループと見なす」と「イントロ時間/ループ時間」\r\n"
            L"    で指定した条件に従います\r\n"
            L" 0: 条件に関わらずループ曲と見なしません。\r\n"
            L" 1: 条件に関わらずループ曲と見なします。\r\n"
            L"    ただし、ループ時間が1小節以下の場合はループ曲と見なしません。\r\n"
            L"\r\n"
            L"本体ドキュメント部の MEAS_REPEAT の値が 0 の曲がイントロがない曲です。\r\n"
            L"MEAS_LOOP が 1 以下のときは設定に関わらずループと見なしません。\r\n"
            L""
            },//help
        {KPI_CFG_TYPE_BOOL, SEC_GENERAL, KEY_INTRO_LOOP, L"イントロがない曲をループと見なす",
            SZ_INTRO_LOOP_DEFAULT, NULL, NULL, //default/min/max
            NULL, //list
            NULL, //listdesc
            L"「ループ判別」が -1(判別条件に従う)のとき有効です。\r\n"
            L"\r\n"
            L"true にするとイントロがない曲をループ曲と見なします。\r\n"
            L"false にするとイントロがない曲はループ曲と見なしません。\r\n"
            L"\r\n"
            L"ループ曲と見なすと連続再生時の演奏時間が「ループ回数」と\r\n"
            L"「フェードアウト時間」の設定に応じた長さになります。\r\n"
            L"\r\n"
            L"ループ曲と見なさなくても「単曲リピート」時には途切れることなくループ再生\r\n"
            L"されますが、連続再生時は演奏終了時にフェードアウトされません。\r\n"
            L"実際にはループ曲だった場合、連続再生時に1回しか再生されず、フェードアウト\r\n"
            L"されずにぷつっと途切れるように演奏終了します。\r\n"
            L"\r\n"
            L"ピストンコラージュ形式では、イントロがない曲の多くはループ曲ではないようです。\r\n"
            L"実際にはループ曲なのにループ曲と見なさなくても、「単曲リピート」時には問題なく\r\n"
            L"ループ再生されますので、既定値は false としています。\r\n"
            L"\r\n"
            L"本体ドキュメント部の MEAS_REPEAT の値が 0 の曲がイントロがない曲です。\r\n"
            L""
            },//help
        {KPI_CFG_TYPE_INT, SEC_GENERAL, KEY_LOOP_RATIO, L"イントロ時間/ループ時間",
            SZ_LOOP_RATIO_DEFAULT, L"1", L"1000", //default/min/max
            L"5\t6\t7\t8\t9\t10\t15\t20\t25\t30\t50\t100", //list
            L"5倍\t6倍\t7倍\t8倍\t9倍\t10倍\t15倍\t20倍\t25倍\t30倍\t50倍\t100倍", //listdesc
            L"「ループ判別」が -1(判別条件に従う)のとき有効です。\r\n"
            L"\r\n"
            L"イントロ時間がループ時間の何倍以内であればループと見なすかの設定です。\r\n"
            L"\r\n"
            L"例えば10倍を指定すると、イントロが100小節ある曲に対してループが10小節以上\r\n"
            L"あればループと見なしますが、ループが9小節以下の場合はループと見なしません。\r\n"
            L"\r\n"
            L"ピストンコラージュ形式では、イントロ時間に対してループ時間が短い曲の多くは\r\n"
            L"ループ曲ではないようですが、ループ曲かどうかを確実に判別する方法はないよう\r\n"
            L"ですので、必要であれば調整して下さい。\r\n"
            L"\r\n"
            L"数値が大きいほど、ループ時間が短くてもループと見なすようになります。\r\n"
            L"ループ時間が1小節以下の場合は設定に関わらずループ曲と見なしません。\r\n"
            L"\r\n"
            L"本体ドキュメント部の MEAS_LOOP の値が 1 以下であるか、MEAS_REPEAT/MEAS_LOOP \r\n"
            L"の値が指定した値以下ならループと見なします。\r\n"
            L""
            },//help
        {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}
    };
    for(int i = 0; sec[i].cszSection; i++){
        pEnumerator->EnumSection(&sec[i]);
    }
    for(int i = 0; key[i].cszSection; i++){
        pEnumerator->EnumKey(&key[i]);
    }
    return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
DWORD __fastcall kbpxtone_ApplyConfig(IKpiConfig *pConfig,
                               const wchar_t *cszSection,//セクション名
                               const wchar_t *cszKey,    //キー名
                               INT64  nValue, //変更後の値(BOOL/INT の場合)
                               double dValue, //変更後の値(FLOAT の場合)
                               const wchar_t *cszValue)////変更後の値(文字列)
{
    /*
        KPI_CFGRET_OK,          //設定は即座に反映される
        KPI_CFGRET_NOTIFY,      //デコーダインスタンス等への変更通知が必要(IKpiXXX::Update()が呼ばれたら反映)
        KPI_CFGRET_RELOAD_DATA, //データの再ロードが必要(次にIKpiXXXModule::Open()が呼ばれた分から反映)
        KPI_CFGRET_RELOAD_KPI,  //プラグインの再ロードが必要
        KPI_CFGRET_REBOOT_PLAYER,//プレイヤー本体の再起動が必要(特別な事情がない限り
                                 //RELOAD_KPI で足りる筈だが)
        KPI_CFGRET_REBOOT_OS,    //OS の再起動が必要
        KPI_CFGRET_UNKNOWN = (DWORD)-1
                                 //不明(外部プログラムを呼び出す等、設定関係の依存
                                 //コードの詳細が分からない等)
    */
    /*if(wcscmp(cszSection, SEC_GENERAL) == 0){
        if(wcscmp(cszKey, KEY_VOLUME) == 0){
            pConfig->SetStr(cszSection, cszKey, cszValue);
            return KPI_CFGRET_NOTIFY;
        }
    }*/
    pConfig->SetStr(cszSection, cszKey, cszValue);
    return KPI_CFGRET_RELOAD_DATA;
}
/////////////////////////////////////////////////////////////////////////////
void __fastcall kbpxtone_GetSettings(IKpiConfig *pConfig, kbpxtone_Settings *pSettings)
{
    pSettings->nSampleRate = pConfig->GetInt(SEC_GENERAL, KEY_SAMPLE_RATE, SAMPLE_RATE_DEFAULT);
    pSettings->dVolume = pConfig->GetFloat(SEC_GENERAL, KEY_VOLUME, VOLUME_DEFAULT);
    pSettings->nLoop = pConfig->GetInt(SEC_GENERAL, KEY_LOOP, LOOP_DEFAULT);
    pSettings->bIntroLoop = pConfig->GetInt(SEC_GENERAL, KEY_INTRO_LOOP, INTRO_LOOP_DEFAULT) != 0;
    pSettings->dwLoopRatio = pConfig->GetInt(SEC_GENERAL, KEY_LOOP_RATIO, LOOP_RATIO_DEFAULT);
    pSettings->dwLoopCount = pConfig->GetInt(SEC_GENERAL, KEY_LOOP_COUNT, LOOP_COUNT_DEFAULT);
    pSettings->nFadeOutMS = pConfig->GetInt(SEC_GENERAL, KEY_FADEOUT, FADEOUT_DEFAULT);
    //値の範囲チェック
    switch(pSettings->nSampleRate){
        case 44100: case 48000: case 88200: case 96000: case 176400: case 192000:
        case -44100: case -48000: case -88200: case -96000: case -176400: case -192000:break;
        default: pSettings->nSampleRate = 44100;break;
    }
    if(pSettings->dVolume < 0.10){
        pSettings->dVolume = 0.10;
    }
    else if(pSettings->dVolume > 1.0){
        pSettings->dVolume = 1.0;
    }
    switch(pSettings->nLoop){
        case -1: case 0: case 1:break;
        default: pSettings->nLoop = LOOP_DEFAULT;break;
    }
    if(pSettings->dwLoopRatio > 1000){
        pSettings->dwLoopRatio = 1000;
    }
    if(pSettings->dwLoopCount > 10){
        pSettings->dwLoopCount = 10;
    }
    if(pSettings->nFadeOutMS < -1){
        pSettings->nFadeOutMS = -1;
    }
    else if(pSettings->nFadeOutMS > 30000){
        pSettings->nFadeOutMS = 30000;
    }
}
/////////////////////////////////////////////////////////////////////////////
