#pragma once

#define STRICT

#include <streams.h>
#include <shlobj.h>
#include <Shlwapi.h>
#include <dmoreg.h>
#include <dmodshow.h>

#include <math.h>

#include<locale>
#include<vector>
using namespace std;

#include "DShowTool.h"
#include "resource.h"

/*
#define SAFE_DELETEARRAY(p)   { if(p!=NULL) { delete [](p); (p)=NULL; } }
#define SAFE_DELETEDC(p)      { if(p!=NULL) { ::DeleteDC(p); (p)=NULL; } }
#define SAFE_RELEASE(p)       { if(p!=NULL) { (p)->Release(); (p)=NULL; } }
#define SAFE_FREEMEDIATYPE(p) { if(p!=NULL) { FreeMediaType(*(p)); (p)=NULL; } }
*/

#define SAFE_DELETEMEDIATYPE(p) { if(p!=NULL) { DeleteMediaType(p); (p)=NULL; } }

#define WM_CONVERT     WM_USER+1
#define WM_GRAPHNOTIFY WM_USER+2
#define WAVE_FORMAT_IEEE_FLOAT 3

#define SAFE_DELETE(p)        { if(p!=NULL) { delete (p); (p)=NULL; } }
#define SAFE_DELETEOBJECT(p)  { if(p!=NULL) { ::DeleteObject(p); (p)=NULL; } }
#define SAFE_FREELIBRARY(p)   { if(p!=NULL) { ::FreeLibrary(p); (p)=NULL; } }

#define FILTER_SOURCE      0
#define FILTER_SPLITTER    0
#define FILTER_DECODEAUDIO 1
#define FILTER_CONVERTWAV  2
#define FILTER_MUX         2
#define FILTER_WRITER      3

/*
#define CONTAINER_WAV_SAME_FORMAT     0
#define CONTAINER_WAV_CHANGE_FORMAT   1
#define CONTAINER_MP3_FRAUNHOFER_CBR 10
*/

#define CONTAINER_MP3_LAME_CBR       20
#define CONTAINER_MP3_LAME_VBR       21
#define CONTAINER_OGG_AOTUV_CBR      30
#define CONTAINER_OGG_AOTUV_VBR      31
#define CONTAINER_OGG_LANCER_CBR     40
#define CONTAINER_OGG_LANCER_VBR     41

#define CONTAINER_RAW     100
#define CONTAINER_RAW_WAV 101
#define CONTAINER_RAW_AAC 102
#define CONTAINER_RAW_OGG 103

#define CONTAINER_RAW_MP2 1010
#define CONTAINER_RAW_MP3 1011
#define CONTAINER_RAW_MP4 1012
#define CONTAINER_RAW_AC3 1013
/*
#define OUTPUT_SAME_FOLDER 0
#define OUTPUT_DIFF_FOLDER 1
*/
/*
enum CONTAINERTYPE
{
   CONTAINER_TYPE_WAV = 0,
   CONTAINER_TYPE_AAC,
   CONTAINER_TYPE_FRAUNHOFER,
   CONTAINER_TYPE_LAME,
   CONTAINER_TYPE_OGG,
   CONTAINER_TYPE_RAW,

   sizeof_CONTAINER_TYPE
};
*/

enum LANGUAGE
{
   JAPANESE = 0,
//   ENGLISH,
//   GERMAN,

   sizeof_LANGUAGE
};


enum GAINMODE
{
   GAIN_NORMALIZE = 1,
   GAIN_AUTOMAXIMIZE,
   GAIN_TRACKGAIN,
   GAIN_ALBUMGAIN
};


#ifdef _DEBUG
   #pragma comment(lib, "strmbasd.lib")
#else
   #pragma comment(lib, "strmbase.lib")
#endif

#pragma comment(lib, "winmm.lib")
#pragma comment(lib, "shlwapi.lib")
#pragma comment(lib, "Dmoguids.lib")

#ifdef _DEBUG
   void testNero(void);
   void makeWavFile(void);
   void testWav(int);
   void testOgg(int);
   void testFraunhofer(int);
   void testLame(int);
#endif
// ------------------------------------------------------------------------------------------------------------------------
struct CONVERTDATA
{
   int nContainerType;
   int nOutputFolder;
   WCHAR awOutputFolder[MAX_PATH];

   WAVEFORMATEX wf;
   int nEncodeMode;
   int nAdvancedMode;
   int nABRCBR;
   int nVBR;
   float fVBR;

   int nPass;
   bool bDirectNeroAacEnc;

   int nGainMode;
   double dGain;
   double dNormalize;

   vector<std::wstring> dropList;
};
// ------------------------------------------------------------------------------------------------------------------------
typedef struct tagVORBISFORMAT
{
	WORD  nChannels;
	long  nSamplesPerSec;
	long  nMinBitsPerSec;
	long  nAvgBitsPerSec;
	long  nMaxBitsPerSec;
	float fQuality;
} VORBISFORMAT;
// ------------------------------------------------------------------------------------------------------------------------
typedef struct
{
   int nMode;
   int nQuality;

   struct
   {
      DWORD dwBitrate;
   } abr;

   struct
   {
      DWORD dwBitrate;
   } cbr;

   struct
   {
      int nVBRQuality;
      DWORD dwMinBitrate;
      DWORD dwMaxBitrate;
   } vbr;
} LAME_CONFIG, *PLAME_CONFIG;
// ------------------------------------------------------------------------------------------------------------------------
__interface IEcoDecoInterface : public IUnknown
{
public:
   HRESULT SetWait(int);
   HRESULT GetInFormat(WAVEFORMATEX *);
   HRESULT GetTransformedBytes(LONGLONG *);
};
// ------------------------------------------------------------------------------------------------------------------------
__interface
IDecodeInterface : public IUnknown
{
public:
   HRESULT GetOutFormat(void *);
   HRESULT SetOutFormat(void *);
};
// ------------------------------------------------------------------------------------------------------------------------
__interface
IEncodeLameInterface: public IUnknown
{
public:
   HRESULT GetOutFormat(void *);
   HRESULT SetOutFormat(void *);
   HRESULT CheckOutFormat(WAVEFORMATEX *, LAME_CONFIG *);
   HRESULT CheckMode(bool);
   HRESULT SetReplaygain(bool, bool);
};
// ------------------------------------------------------------------------------------------------------------------------
__interface
IConvertWavInterface : public IUnknown
{
public:
   HRESULT GetInFormat(WAVEFORMATEX *);
   HRESULT GetOutFormat(WAVEFORMATEX *);
   HRESULT SetOutFormat(WAVEFORMATEX *);

   HRESULT SetNormalize(bool, double);
   HRESULT SetReplaygain(bool);
   HRESULT GetReplaygainResult(double *, double *);
};
// ------------------------------------------------------------------------------------------------------------------------
__interface
IEncodeFraunhoferInterface: public IUnknown
{
public:
   HRESULT SetOutFormat(void *);
   HRESULT CheckOutFormat(WAVEFORMATEX *, int *);
   HRESULT CheckMode(bool);
   HRESULT SetReplaygain(bool, bool);
};
// --------------------------------------------------------------------------------------------------------------------
__interface IEncodeVorbisInterface : public IUnknown
{
public:
   HRESULT CheckOutFormat(void *);
   HRESULT GetOutFormat(void *);
   HRESULT SetOutFormat(void *);
   HRESULT CheckMode(bool);
   HRESULT SetReplaygain(bool, bool);
};
// --------------------------------------------------------------------------------------------------------------------
__interface IEcoDecoWriterInterface : public IUnknown
{
public:
   int GetOutputMode(void);
   void SetOutputMode(int);
   HRESULT CheckMode(bool);
   HRESULT SetReplaygain(bool, bool);
};
// ------------------------------------------------------------------------------------------------------------------------
struct FilterData
{
   HMODULE hDLL;
   CLSID clsid;
};
// ------------------------------------------------------------------------------------------------------------------------
class CDirectShow
{
private:

   // ユーザ関数
   HRESULT RenderWma(IGraphBuilder *, WCHAR *, IBaseFilter *, bool);
   HRESULT RenderByAllFilter(IGraphBuilder *, WCHAR *, IBaseFilter *, bool);
   HRESULT RenderByFileExt(IGraphBuilder *, WCHAR *, IBaseFilter *, bool);
   HRESULT RenderAudio(IGraphBuilder *, IBaseFilter *, IBaseFilter *, bool);
   IBaseFilter *AddSourceFilter(FilterData *, IGraphBuilder *, WCHAR *, CLSID, WCHAR *);
   IBaseFilter *AddFilter(FilterData *, IGraphBuilder *, WCHAR *, CLSID);

   // ユーザ変数
   IGraphBuilder *m_pGraphBuilder;
   IMediaEventEx *m_pMediaEventEx;
   IMediaControl *m_pMediaControl;
   IEcoDecoInterface *m_pEcoDecoInterface;
   IConvertWavInterface *m_pConvertWavInterface;
   LONGLONG m_llTotalBytes;
   WAVEFORMATEX m_InputFormat;
   WAVEFORMATEX m_OutputFormat;

   CDShowTool dshowTool;
   FilterData m_filterData[4];

   int m_nRawFileType;

public:
   CDirectShow();
   ~CDirectShow();

   // ユーザ関数
   void Release();
   int WaitForCompletion(void);
   int PlayEnd(void);
   int GetRawFileType(void);
   int GetPercent(void);
   HRESULT GetReplaygainResult(double *, double *);
   void SetWait(int);
   void GetFormat(WAVEFORMATEX *, WAVEFORMATEX *);
   bool ReConvert(void);
   bool ConvertToWav(HWND, WCHAR *, WCHAR *, CONVERTDATA *, bool, int);
   bool ConvertToFraunhoferMP3(HWND, WCHAR *, WCHAR *, CONVERTDATA *, bool, int);
   bool ConvertToLameMP3(HWND, WCHAR *, WCHAR *, CONVERTDATA *, bool, int);
   bool ConvertToOgg(HWND, WCHAR *, WCHAR *, CONVERTDATA *, bool, int);
   bool ConvertRaw(HWND, WCHAR *, WCHAR *, int);
};
// ------------------------------------------------------------------------------------------------------------------------
class CReplayGain
{
private:

   void GetCRC32(DWORD *, BYTE *, int);
   HRESULT WriteID3v2Tag(HANDLE, int, double, double, double, double);

public:

   HRESULT OverWriteMp3AlbumGain(WCHAR *, double, double);
   HRESULT WriteLame(WCHAR *, int, double, double, double, double);
   HRESULT WriteFraunhofer(WCHAR *, int, double, double, double, double);
   HRESULT WriteWav(WCHAR *, int, double, double);
   HRESULT WriteOgg(WCHAR *, int, double, double);
};
// ------------------------------------------------------------------------------------------------------------------------
class CConvertDialog
{
private:

   void AddListFromFolder(HWND, WCHAR *);
   void GetInputFileName(HWND);
   void DoEvents(HWND);
   bool ConvertToAac(WCHAR *, WCHAR *, PROCESS_INFORMATION *);
   void Convert(HWND);
   void GetOutputFileName(WCHAR *, CONVERTDATA *, WCHAR *, bool);
   bool ConvertStart(HWND, CONVERTDATA *, WCHAR *, WCHAR *, bool, int);
   void ConvertGetPercent(HWND);
   void ConvertExit(HWND);
   void ConvertEnd(HWND, int);

   void InitDialog(HWND);
   void EndDialog(HWND);
   static LRESULT CALLBACK DialogProc(HWND, UINT, WPARAM, LPARAM);

   int m_nLanguage;

   double m_dAlbumGain;
   double m_dAlbumPeak;

   bool m_bExit;
   int m_nCurrentCpuUsage;
   int m_nNewCpuUsage;
   int m_nCurrentNumber;
   int m_nErrorCount;
   int m_nCurrentPercent;
   int m_nConvertState;
   WCHAR m_awCurrentOutputFileName[MAX_PATH];
   WCHAR m_awTmpFileName[MAX_PATH];
   vector<std::wstring> m_inputFileList;
   CONVERTDATA m_convertData;
   CDirectShow *m_pDirectShow;
   PROCESS_INFORMATION m_pi;

public:
   CConvertDialog();
   ~CConvertDialog();
   void Show(CONVERTDATA *, int);
};
// ----------------------------------------------------------------------------------------------------------------------------
class CMainDialog
{
public:

   CMainDialog();
   ~CMainDialog();

   // ユーザ関数
   bool LoadSetting(CONVERTDATA *);
   bool ShowDialog(CONVERTDATA *, int);

private:

   // ユーザ関数
   int GetPrivateProfileInt(WCHAR *, WCHAR *, int, int, int, WCHAR *);
   void PrepareComboBox(HWND, int, WCHAR *, int);
   void SetComboBoxCursel(WCHAR *, HWND, int);
   void WriteIniFile(WCHAR *, HWND, int, WCHAR *);
   bool GetReplaygain(HWND, int, double *);
   bool GetSettingData(HWND);
   static int CALLBACK SHBrowseProc(HWND, UINT, LPARAM,  LPARAM);
   bool DropFiles(HWND, HDROP);
   void SelectFolder(HWND);
   void SelectMode(HWND, int, int);
   void SelectContainer(HWND, int);
   void OnCreate(HWND);
   void OnClose(HWND);
   void OnPaint(HDC);
   void DrawCustomRoundRect(HDC, RECT *);
   void DrawHoverButton(DRAWITEMSTRUCT *, int);
   void DrawItem(DRAWITEMSTRUCT *);
   static LRESULT CALLBACK DialogWaveFormatProc(HWND, UINT, WPARAM, LPARAM);
   static LRESULT CALLBACK CustomProc(HWND, UINT, WPARAM, LPARAM);
   static LRESULT CALLBACK DialogProc(HWND, UINT, WPARAM, LPARAM);
   bool ExistsNeroAAC(void);
   bool ExistsFraunhoferPro(void);
   bool ExistsLameEnc(void);

   // ユーザ定数
/*
   enum MYPROC
   {
      BUTTON_MIN = 0,
      BUTTON_CLOSE,
      BUTTON_HELP_CONTAINER,
      BUTTON_HELP_DROPFILE,
      BUTTON_SETTING_WAVFORMAT,
      BUTTON_SETTING_OUTFOLDER,
      LINK_AAC,
      LINK_FRAUNHOFER,
      LINK_LAME,
      EDIT_REPLAYGAIN_AAC,
      EDIT_REPLAYGAIN_FRAUNHOFER,
      EDIT_REPLAYGAIN_LAME,
      EDIT_REPLAYGAIN_OGG,

      sizeof_MYPROC
   };

   enum ITEM
   {
      DIALOG_BUTTON = 0,
      DIALOG_LINKLABEL,
      DIALOG_EDITBOX
   };

   struct PROC
   {
      int nItemType;
      int nResourceID;
      WNDPROC proc;
   };
*/

   enum ITEM
   {
      DIALOG_BUTTON = 0,
      DIALOG_LINKLABEL,
      DIALOG_EDITBOX
   };

   struct PROC
   {
      int nItemType;
      int nResourceID;
      WNDPROC proc;
   };

   // ユーザ変数
//   CONVERTDATA *m_pConvertData;
   CONVERTDATA m_convertData;

   enum{ sizeof_MYPROC = 14 };
   PROC m_myProc[sizeof_MYPROC];

   int m_nLanguage;

   int m_nAlpha;
   HRGN m_hRgn;
   int m_nMinResourceID;
   int m_nCloseResourceID;

   bool m_bExistsNeroAAC;
   bool m_bExistsFraunhoferPro;
   bool m_bExistsLameEnc;
   WAVEFORMATEX m_waveFormat;
};
// ----------------------------------------------------------------------------------------------------------------------------
