#pragma once

#include "./vstsdk/aeffectx.h"

class VstiHost;
class VstiLoader
{
private:
    friend class VstiHost;
    enum {
        WM_DISPATCHER = WM_APP,
        WM_PROCESS_REPLACING,
        WM_SHOW_EDITOR,
        WM_CLOSE_EDITOR,
        WM_EFFOPEN,
        WM_EFFCLOSE,
    };
    struct DISPATCHER_PARAM {
        VstInt32  opcode;
        VstInt32  index;
        VstIntPtr value;
        void     *ptr;
        float     opt;
        VstIntPtr retval;//戻り値
    };
    struct SHOW_EDITOR_PARAM {
        int pos_x;
        int pos_y;
        WNDPROC WndProc;
        void *pvInstance;
    };
    struct PROCESS_REPLACING_PARAM {
        void   **inputs; //NULL を渡すと落ちるプラグインがある
        void   **outputs;
        VstInt32 sampleFrames;
        bool     is_double;
    };
    enum{
        MAX_CACHE = 4
    };
    typedef AEffect* (*pfnVSTPluginMain)(audioMasterCallback);
    HINSTANCE   m_hDll;
    wchar_t     m_szPath[MAX_PATH];
    DWORD       m_dwThreadId;
    pfnVSTPluginMain m_VSTPluginMain;
    HWND        m_hWnd;    //↓のスレッドで作成するウィンドウのハンドル
    HANDLE      m_hThread; //プラグインを使用するスレッド
    HANDLE      m_hEventInit;//初期化完了時にシグナル
    HANDLE      m_hEventExit;//終了時にシグナル
    static VstIntPtr VSTCALLBACK HostCallback(AEffect* effect, VstInt32 opcode, VstInt32 index, VstIntPtr value, void* ptr, float opt);
    static LRESULT CALLBACK VstiWndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp);
    LRESULT VstiWndProcInternal(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp);
    static unsigned __stdcall ThreadProc(void* pThis) {
        return ((VstiLoader*)pThis)->ThreadProc();
    }
    unsigned ThreadProc(void);
    VstiHost *m_pCache[MAX_CACHE];
public:
    VstiLoader(void);
    ~VstiLoader(void);
    bool Init(const wchar_t *cszPath);
    VstiHost* GetVsti(void);
    void CacheVsti(VstiHost *pVsti);
    void FreeVsti(VstiHost *pVsti, bool bCache);
};

