/**************************************************************************
 * Copyright (C) 2008 Cocha                                               *
 * http://sourceforge.jp/projects/ecodecotool/                            *
 *                                                                        *
 *  This Program is free software; you can redistribute it and/or modify  *
 *  it under the terms of the GNU General Public License as published by  *
 *  the Free Software Foundation; either version 2, or (at your option)   *
 *  any later version.                                                    *
 *                                                                        *
 *  This Program is distributed in the hope that it will be useful,       *
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the          *
 *  GNU General Public License for more details.                          *
 *                                                                        *
 *  You should have received a copy of the GNU General Public License     *
 *  along with GNU Make; see the file COPYING.  If not, write to          *
 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. *
 *                                                                        *
 **************************************************************************/

#include "EcoDecoTooL.h"

#define TIMER_GETINPUTFILENAME 1
#define TIMER_CONVERT          2
#define TIMER_GETPERCENT       3


struct LOCALEDATA
{
   struct ERROR_MESSAGE
   {
      WCHAR *pwConvert;
      WCHAR *pwDropFile;
   } error;

   WCHAR *pwResult;
   WCHAR *pwCpuUsage[5];
   WCHAR *pwInputSameFormat;

   WCHAR *pwDropCount;
   WCHAR *pwDropFile;

   WCHAR *pwAnalyzeStart[2];
   WCHAR *pwAnalyzing[4];
   WCHAR *pwConvertStart[2];
   WCHAR *pwConverting[4];
   WCHAR *pwNeroConverting[2];
   WCHAR *pwExtracting[2];
   WCHAR *pwTagOutput[2];

   WCHAR *pwRawInput;
};

static LOCALEDATA g_localeData[sizeof_LANGUAGE] =
{
   {
      L"変換できませんでした",
      L"ファイルが存在しません",

      L"成功：%d　/ 失敗：%d",
      L"最低", L"低い", L"普通", L"高い", L"最高",
      L"入力と同じ",

      L"ファイルカウント中 %d個",
      L"ドロップファイル処理中",

      L"音量解析開始", L"[%d/%d] 音量解析開始",
      L"音量解析中", L"[%d/%d] 音量解析中", L"%3d%% 音量解析中", L"[%d/%d]%3d%% 音量解析中",

      L"変換開始", L"[%d/%d] 変換開始",
      L"変換中", L"[%d/%d] 変換中", L"%3d%% 変換中", L"[%d/%d]%3d%% 変換中",
      L"NeroAacEnc 変換中", L"[%d/%d] NeroAacEnc 変換中",
      L"抽出中", L"[%d/%d] 抽出中",
      L"Albumゲイン処理中", L"[%d/%d] Albumゲイン処理中",

      L"入力音声："
   }
};


static CConvertDialog *g_pMyClass = NULL; 
CConvertDialog::CConvertDialog()
{
   g_pMyClass = this;
   m_pDirectShow = NULL;

   m_bExit = false;
   m_nConvertState = 0;

   m_nCurrentCpuUsage = 0;
   m_nNewCpuUsage = 0;

   m_dAlbumGain = 0;
   m_dAlbumPeak = 0;

   m_nCurrentNumber = 0;
   m_nErrorCount = 0;
   m_nCurrentPercent = 0;
   ::ZeroMemory(m_awCurrentOutputFileName, sizeof(m_awCurrentOutputFileName));
   ::ZeroMemory(m_awTmpFileName, sizeof(m_awTmpFileName));

   ::ZeroMemory(&m_pi, sizeof(m_pi));

   m_inputFileList.clear();

   m_pDirectShow = new CDirectShow();
}
CConvertDialog::~CConvertDialog()
{
   if(m_pDirectShow != NULL)
   {
      delete m_pDirectShow;
      m_pDirectShow = NULL;
   }

   if(m_pi.hProcess != NULL)
   {
      ::CloseHandle(m_pi.hProcess);
      m_pi.hProcess = NULL;
   }
}
void CConvertDialog::AddListFromFolder(HWND hWnd, WCHAR *pwFilePath)
{  

   HANDLE handle = NULL;
   WIN32_FIND_DATA find_data;
   WCHAR szSearch[MAX_PATH], awInputFileName[MAX_PATH];

   if(pwFilePath[::lstrlen(pwFilePath)-1] != '\\')
      ::lstrcat(pwFilePath, L"\\");

   ::lstrcpy(szSearch, pwFilePath);
   ::lstrcat(szSearch, L"*.*");

   handle = ::FindFirstFile(szSearch, &find_data);

   if (handle == INVALID_HANDLE_VALUE)
   {
      if(handle != NULL)
         ::FindClose(handle);

      return;
   }

   do
   {
      DoEvents(hWnd);

      if(m_bExit == true)
      {
         ::FindClose(handle);
         return;
      }

      if(::lstrcmp(find_data.cFileName, L".") == 0 ||
         ::lstrcmp(find_data.cFileName, L"..") == 0)
      {  
      }
      else if( (find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) !=0)
      {  

         WCHAR awNextFolder[MAX_PATH];
         ::wsprintf(awNextFolder, L"%s%s", pwFilePath, find_data.cFileName);

         if(::PathIsSystemFolder(awNextFolder, 0) == FALSE)
            AddListFromFolder(hWnd, awNextFolder);
      }
      else
      {  

         ::lstrcpy(awInputFileName, pwFilePath);
         ::lstrcat(awInputFileName, find_data.cFileName);

         m_inputFileList.push_back(awInputFileName);

         if((int)m_inputFileList.size() % 10 == 0)
         {
            WCHAR awText[MAX_PATH];
            ::wsprintf(awText, g_localeData[m_nLanguage].pwDropCount, (int)m_inputFileList.size());
            ::SetWindowText(hWnd, awText);
            DoEvents(hWnd);
         }

      }
   } while (::FindNextFile(handle, &find_data));

   ::FindClose(handle);
}
void CConvertDialog::GetInputFileName(HWND hWnd)
{  

   int i, nSize;
   WCHAR awText[MAX_PATH];

   ::SetDlgItemText(hWnd, IDC_STATIC_CONVERT_FILENAME, g_localeData[m_nLanguage].pwDropFile);

   nSize = (int)m_convertData.dropList.size();
   for(i=0;i<nSize;i++)
   {
      if(::PathIsDirectory(m_convertData.dropList[i].c_str()) == FALSE)
      {
         m_inputFileList.push_back(m_convertData.dropList[i].c_str());

         if((int)m_inputFileList.size() % 10 == 0)
         {
            ::wsprintf(awText, g_localeData[m_nLanguage].pwDropCount, (int)m_inputFileList.size());
            ::SetWindowText(hWnd, awText);
            DoEvents(hWnd);
         }
      }
      else
      {
         ::lstrcpy(awText, m_convertData.dropList[i].c_str());
         AddListFromFolder(hWnd, awText);
      }

      if(m_bExit == true)
         return;
   }
}
void CConvertDialog::DoEvents(HWND hWnd)
{
   MSG msg;

   while(::PeekMessage(&msg, hWnd, 0, 0, PM_REMOVE))
   {
      ::TranslateMessage(&msg);
      ::DispatchMessage(&msg); 
   }
}
bool CConvertDialog::ConvertToAac(WCHAR *pwInputFileName, WCHAR *pwOutputFileName, PROCESS_INFORMATION *pi)
{
   WCHAR awText[32], awCommandLine[1024];

   ::GetModuleFileName(NULL, awCommandLine, 1024);
   ::PathRemoveFileSpec(awCommandLine);
   ::lstrcat(awCommandLine, L"\\NeroAacEnc.exe ");

   if(m_convertData.nEncodeMode == 0)
      swprintf_s(awText, 32, L"-br %d ", m_convertData.nABRCBR);
   else if(m_convertData.nEncodeMode == 1)
      swprintf_s(awText, 32, L"-cbr %d ", m_convertData.nABRCBR);
   else 
      swprintf_s(awText, 32, L"-q %1.1f ", m_convertData.fVBR);

   ::lstrcat(awCommandLine, awText);

   if(m_convertData.nEncodeMode == 0)
      ::lstrcat(awCommandLine, L"-2pass ");

   if(m_convertData.nAdvancedMode == 1)
      ::lstrcat(awCommandLine, L"-lc ");
   else if(m_convertData.nAdvancedMode == 2)
      ::lstrcat(awCommandLine, L"-he ");
   else if(m_convertData.nAdvancedMode == 3)
      ::lstrcat(awCommandLine, L"-hev2 ");

   ::lstrcat(awCommandLine, L"-if ");
   ::lstrcat(awCommandLine, L"\"");
   ::lstrcat(awCommandLine, pwInputFileName);
   ::lstrcat(awCommandLine, L"\"");

   ::lstrcat(awCommandLine, L" -of ");
   ::lstrcat(awCommandLine, L"\"");
   ::lstrcat(awCommandLine, pwOutputFileName);
   ::lstrcat(awCommandLine, L"\"");

   STARTUPINFO si;
   ::ZeroMemory(&si, sizeof(STARTUPINFO));
   si.cb          = sizeof(STARTUPINFO);
   si.dwFlags     = STARTF_USESHOWWINDOW;
   si.wShowWindow = SW_HIDE;

   ::CreateProcess(NULL, awCommandLine, NULL, NULL, FALSE, DETACHED_PROCESS,NULL, NULL, &si, pi);
   ::CloseHandle(m_pi.hThread);

   return true;
}
void CConvertDialog::Convert(HWND hWnd)
{  

   bool flag;
   int nListSize;
   WCHAR awText[MAX_PATH]; 
   WCHAR awInputFileName[MAX_PATH], awOutputFileName[MAX_PATH];

   nListSize = (int)m_inputFileList.size();


   if(m_convertData.nGainMode == GAIN_ALBUMGAIN && m_convertData.nPass == 2)
   {  

      ::lstrcpy(awInputFileName, m_inputFileList[m_nCurrentNumber].c_str());
      GetOutputFileName(awOutputFileName, &m_convertData, awInputFileName, false);
      ::lstrcpy(m_awCurrentOutputFileName, awOutputFileName);

      if(nListSize == 1)
         ::lstrcpy(awText, g_localeData[m_nLanguage].pwTagOutput[0]);
      else
         ::wsprintf(awText, g_localeData[m_nLanguage].pwTagOutput[1], m_nCurrentNumber+1, nListSize);

      ::SetWindowText(hWnd, awText);

      m_nConvertState = EC_COMPLETE;
      ConvertEnd(hWnd, m_nConvertState);

      return;
   }

   if(m_nCurrentNumber % 100 == 99)
   {
      ::CoUninitialize();
      ::CoInitialize(NULL);
   }

   if( (m_convertData.nGainMode == GAIN_NORMALIZE || m_convertData.nGainMode == GAIN_AUTOMAXIMIZE) && m_convertData.nPass == 1)
   {  
      if(nListSize == 1)
         ::lstrcpy(awText, g_localeData[m_nLanguage].pwAnalyzeStart[0]);
      else
         ::wsprintf(awText, g_localeData[m_nLanguage].pwAnalyzeStart[1], m_nCurrentNumber+1, nListSize);
   }
   else
   {  
      if(nListSize == 1)
         ::lstrcpy(awText, g_localeData[m_nLanguage].pwConvertStart[0]);
      else
         ::wsprintf(awText, g_localeData[m_nLanguage].pwConvertStart[1], m_nCurrentNumber+1, nListSize);
   }

   ::SetWindowText(hWnd, awText);

   ::lstrcpy(awInputFileName, m_inputFileList[m_nCurrentNumber].c_str());
   ::SetDlgItemText(hWnd, IDC_STATIC_CONVERT_FILENAME, ::PathFindFileName(awInputFileName));

   ::InvalidateRect(hWnd, NULL, TRUE);
   DoEvents(hWnd);

   if(m_convertData.nContainerType == 1 && m_convertData.bDirectNeroAacEnc == false && m_convertData.nPass == 2)
   {  
      ::lstrcpy(awOutputFileName, m_awTmpFileName);
   }
   else
   {
      GetOutputFileName(awOutputFileName, &m_convertData, awInputFileName,true);
   }

   m_nCurrentPercent = 0;

   if(m_bExit == true)
      return;

   int nWait = ::SendMessage(::GetDlgItem(hWnd, IDC_COMBO_CPU), CB_GETCURSEL, (WPARAM)0, (LPARAM)0);
   switch(nWait)
   {
   case 0: nWait = 4; break;
   case 1: nWait = 3; break;
   case 2: nWait = 2; break;
   case 3: nWait = 1; break;
   case 4: nWait = 0; break;
   default: nWait = 1; break;
   }

   m_nNewCpuUsage = m_nCurrentCpuUsage;

   m_nConvertState = 0;

   if(m_convertData.nContainerType == 1 && m_convertData.nPass == 2)
   {  

   }
   else
   {
      ::lstrcpy(m_awCurrentOutputFileName, awOutputFileName);
   }

   if(m_convertData.nContainerType == 1)
   {  
      if(m_convertData.nPass == 1)
      {  

         HANDLE hFile = NULL;
         int nSignature;
         WAVEFORMATEX wf;
         DWORD dwRead;

         hFile = ::CreateFile(awInputFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, (DWORD)0, NULL);
         if(hFile != NULL && hFile != (HANDLE)0xffffffff)
         {
            ::ReadFile(hFile, &nSignature, 4, &dwRead, NULL);
            if(dwRead == 4)
            {
               if(nSignature == 0x46464952) 
               {
                  ::SetFilePointer(hFile, 16, NULL, FILE_CURRENT);

                  ::ReadFile(hFile, &wf, sizeof(wf), &dwRead, NULL);
                  if(dwRead == sizeof(wf))
                  {
                     if(wf.wFormatTag == 1 || wf.wFormatTag == 3)
                     {
                        if(wf.nSamplesPerSec <= 96000 && wf.wBitsPerSample <= 32)
                        {
                           m_convertData.bDirectNeroAacEnc = true;
                           m_convertData.nPass = 2;
                           ::lstrcpy(m_awTmpFileName, awInputFileName);
                        }
                     }
                  }
               }
            }

            ::CloseHandle(hFile);
         }

         if(m_convertData.nPass == 1)
         {
            m_convertData.bDirectNeroAacEnc = false;
            flag = ConvertStart(hWnd, &m_convertData, awInputFileName, awOutputFileName, false, nWait);

            if(flag == true)
               ::lstrcpy(m_awTmpFileName, awOutputFileName);
            else
               ::lstrcpy(m_awTmpFileName, L"");
         }
      }

      if(m_convertData.nPass == 2)
      {  
         ::PathRenameExtension(awOutputFileName, L".m4a");
         flag = ConvertToAac(m_awTmpFileName, awOutputFileName, &m_pi);
      }
   }
   else if(m_convertData.nGainMode == GAIN_NORMALIZE || m_convertData.nGainMode == GAIN_AUTOMAXIMIZE)
   {  
      if(m_convertData.nPass == 1)
      {  
         flag = ConvertStart(hWnd, &m_convertData, awInputFileName, awOutputFileName, true, nWait);
      }
      else
      {  
         flag = ConvertStart(hWnd, &m_convertData, awInputFileName, awOutputFileName, false, nWait);
      }
   }
   else
   {  

      flag = ConvertStart(hWnd, &m_convertData, awInputFileName, awOutputFileName, false, nWait);
   }

   if(m_bExit == true)
      return;

   if(flag == true)
   {  

      if(m_convertData.nContainerType < 5)
      {
         if( (m_convertData.nGainMode == GAIN_NORMALIZE || m_convertData.nGainMode == GAIN_AUTOMAXIMIZE) && m_convertData.nPass == 1)
         {  
            if(nListSize == 1)
               ::wsprintf(awText, g_localeData[m_nLanguage].pwAnalyzeStart[0]);
            else
               ::wsprintf(awText, g_localeData[m_nLanguage].pwAnalyzeStart[1], m_nCurrentNumber+1, nListSize);
         }
         else
         {  
            if(nListSize == 1)
               ::wsprintf(awText, g_localeData[m_nLanguage].pwConvertStart[0]);
            else
               ::wsprintf(awText, g_localeData[m_nLanguage].pwConvertStart[1], m_nCurrentNumber+1, nListSize);
         }
      }
      else
      {  
         if(nListSize == 1)
            ::wsprintf(awText, g_localeData[m_nLanguage].pwExtracting[0]);
         else
            ::wsprintf(awText, g_localeData[m_nLanguage].pwExtracting[1], m_nCurrentNumber+1, nListSize);
      }

      ::SetWindowText(hWnd, awText);

      if(m_convertData.nContainerType < 5)
      {  

         WAVEFORMATEX inputFormat, outputFormat;

         m_pDirectShow->GetFormat(&inputFormat, &outputFormat);

         if(m_convertData.nContainerType == 1 && m_convertData.nPass == 2)
            ::lstrcpy(awText, L"-");
         else
            ::wsprintf(awText, L"%dHz %2dbit %dch", inputFormat.nSamplesPerSec, inputFormat.wBitsPerSample, inputFormat.nChannels);

         ::SetDlgItemText(hWnd, IDC_STATIC_CONVERT_INPUT_FORMAT, awText);

         if(m_convertData.nContainerType == 1 && m_convertData.nPass == 2)
            ::lstrcpy(awText, L"-");
         else
         {
            if(m_convertData.nContainerType == 0 && m_convertData.wf.nSamplesPerSec == 0 && m_convertData.wf.wBitsPerSample == 0 && m_convertData.wf.nChannels == 0)
               ::lstrcpy(awText, g_localeData[m_nLanguage].pwInputSameFormat);
            else
               ::wsprintf(awText, L"%dHz %2dbit %dch", outputFormat.nSamplesPerSec, outputFormat.wBitsPerSample, outputFormat.nChannels);
         }

         ::SetDlgItemText(hWnd, IDC_STATIC_CONVERT_OUTPUT_FORMAT, awText);
      }
      else
      {  
         int nFileType;

         nFileType = m_pDirectShow->GetRawFileType();

         if(nFileType == CONTAINER_RAW_AAC)
            ::lstrcpy(awText, L"aac");
         else if(nFileType == CONTAINER_RAW_AC3)
            ::lstrcpy(awText, L"ac3");
         else if(nFileType == CONTAINER_RAW_MP2)
            ::lstrcpy(awText, L"mp2");
         else  if(nFileType == CONTAINER_RAW_MP3)
            ::lstrcpy(awText, L"mp3");
         else  if(nFileType == CONTAINER_RAW_MP4)
            ::lstrcpy(awText, L"mp4");
         else  if(nFileType == CONTAINER_RAW_OGG)
            ::lstrcpy(awText, L"ogg");
         else
            ::lstrcpy(awText, L"-");

         ::SetDlgItemText(hWnd, IDC_STATIC_CONVERT_INPUT_FORMAT, awText);
      }

      ::InvalidateRect(hWnd, NULL, TRUE);

      ::SetTimer(hWnd, TIMER_GETPERCENT, 110, NULL);
   }
   else
   {  

      m_nErrorCount++;
      m_nCurrentNumber++;

      m_pDirectShow->Release();

      if(::PathFileExists(m_awCurrentOutputFileName) != FALSE)
         ::DeleteFile(m_awCurrentOutputFileName);

      ::wsprintf(awText, g_localeData[m_nLanguage].pwResult, m_nCurrentNumber - m_nErrorCount, m_nErrorCount);
      ::SetDlgItemText(hWnd, IDC_STATIC_CONVERT_RESULT, awText);
      ::InvalidateRect(hWnd, NULL, TRUE);
      DoEvents(hWnd);

      if(m_nCurrentNumber < (int)m_inputFileList.size())
      {  

         ::SetTimer(hWnd, TIMER_CONVERT, 55, NULL);
      }
      else
      {  

         if(m_nErrorCount < (int)m_inputFileList.size())
         {
            ::PlaySound(MAKEINTRESOURCE(IDR_WAVE), ::GetModuleHandle(NULL), SND_RESOURCE|SND_ASYNC);

            for (int i=0;i<4;i++)
            {
               ::FlashWindow(hWnd, TRUE);
               ::Sleep(500);
               ::FlashWindow(hWnd, FALSE);
            }
         }
         else
         {
            ::MessageBox(hWnd, g_localeData[m_nLanguage].error.pwConvert, L"EcoDecoTooL error", MB_OK);
         }

         m_bExit = true;
         EndDialog(hWnd);
         ::EndDialog(hWnd, IDOK);
      }
   }
}
void CConvertDialog::GetOutputFileName(WCHAR *pawOutputFileName, CONVERTDATA *pConvertData, WCHAR *pawInputFileName, bool bExistsDelete)
{  

   WCHAR awFileExt[MAX_PATH];

   if(pConvertData->nOutputFolder == 0)
      ::lstrcpy(pawOutputFileName, pawInputFileName);
   else  
      ::wsprintf(pawOutputFileName, L"%s\\%s", pConvertData->awOutputFolder, ::PathFindFileName(pawInputFileName));

   switch(pConvertData->nContainerType)
   {
   case 0: 
      ::PathRenameExtension(pawOutputFileName, L".wav");
      break;
   case 1: 
      ::PathRenameExtension(pawOutputFileName, L".wav");
      break;
   case 2: 
      ::PathRenameExtension(pawOutputFileName, L".mp3");
      break;
   case 3: 
      ::PathRenameExtension(pawOutputFileName, L".mp3");
      break;
   case 4: 
      ::PathRenameExtension(pawOutputFileName, L".ogg");
      break;
   case 5: 
      ::PathRemoveExtension(pawOutputFileName);
      break;
   }

   if(::lstrcmpi(pawInputFileName, pawOutputFileName) == 0)
   {  
      ::lstrcpy(awFileExt, ::PathFindExtension(pawOutputFileName));
      ::PathRemoveExtension(pawOutputFileName);
      ::lstrcat(pawOutputFileName, L"_");
      ::lstrcat(pawOutputFileName, awFileExt);
   }

   if(bExistsDelete == true)
   {
      if(::PathFileExists(pawOutputFileName) != FALSE)
      {
         if(::DeleteFile(pawOutputFileName) == FALSE)
         {  
            ::lstrcpy(awFileExt, ::PathFindExtension(pawOutputFileName));
            ::PathRemoveExtension(pawOutputFileName);
            ::lstrcat(pawOutputFileName, L"_");
            ::lstrcat(pawOutputFileName, awFileExt);
         }
      }
   }
}
bool CConvertDialog::ConvertStart(HWND hWnd, CONVERTDATA *pConvertData, WCHAR *pawInputFileName, WCHAR *pawOutputFileName, bool bCheckMode, int nWait)
{  

   switch(pConvertData->nContainerType)
   {
   case 0:  
      return (m_pDirectShow->ConvertToWav(hWnd, pawInputFileName, pawOutputFileName, pConvertData, bCheckMode, nWait));
   case 1:  
      return (m_pDirectShow->ConvertToWav(hWnd, pawInputFileName, pawOutputFileName, pConvertData, bCheckMode, nWait));
   case 2:  
      return (m_pDirectShow->ConvertToFraunhoferMP3(hWnd, pawInputFileName, pawOutputFileName, pConvertData, bCheckMode, nWait));
   case 3:  
      return (m_pDirectShow->ConvertToLameMP3(hWnd, pawInputFileName, pawOutputFileName, pConvertData, bCheckMode, nWait));
   case 4:  
      return (m_pDirectShow->ConvertToOgg(hWnd, pawInputFileName, pawOutputFileName, pConvertData, bCheckMode, nWait));
   case 5:  
      return (m_pDirectShow->ConvertRaw(hWnd, pawInputFileName, pawOutputFileName, nWait));
   }

   return false;
}
void CConvertDialog::ConvertGetPercent(HWND hWnd)
{
   WCHAR awText[MAX_PATH];

   if(m_nCurrentCpuUsage != m_nNewCpuUsage)
   {
      switch(m_nNewCpuUsage)
      {
      case 0: m_pDirectShow->SetWait(4); break;
      case 1: m_pDirectShow->SetWait(3); break;
      case 2: m_pDirectShow->SetWait(2); break;
      case 3: m_pDirectShow->SetWait(1); break;
      case 4: m_pDirectShow->SetWait(0); break;
      }

      m_nCurrentCpuUsage = m_nNewCpuUsage;
   }

   if(m_convertData.nContainerType == 1 && m_convertData.nPass == 2)
   {  

      DWORD dwResult;
      dwResult = ::WaitForSingleObject(m_pi.hProcess, 50);

      if(dwResult == WAIT_OBJECT_0)
      {  
         m_nConvertState = EC_COMPLETE;

         ::CloseHandle(m_pi.hProcess);
         m_pi.hProcess = NULL;
      }

      if((int)m_inputFileList.size() == 1)
         ::lstrcpy(awText, g_localeData[m_nLanguage].pwNeroConverting[0]);
      else
         ::wsprintf(awText, g_localeData[m_nLanguage].pwNeroConverting[1], m_nCurrentNumber+1, (int)m_inputFileList.size());

      for(int j=0;j<m_nCurrentPercent;j++)
         ::lstrcat(awText, L".");

      ::SetWindowText(hWnd, awText);

      m_nCurrentPercent++;
      if(m_nCurrentPercent > 3)
         m_nCurrentPercent = 0;
   }
   else if(m_convertData.nContainerType < 5)
   {  

      int nNewPercent;

      nNewPercent = m_pDirectShow->GetPercent();
      if(nNewPercent >= 0)
      {
         if(nNewPercent > 100)
            nNewPercent = 100;

         if(nNewPercent != m_nCurrentPercent)
         {
            if( (m_convertData.nGainMode == GAIN_NORMALIZE || m_convertData.nGainMode == GAIN_AUTOMAXIMIZE) && m_convertData.nPass == 1)
            {  
               if((int)m_inputFileList.size() == 1)
                  ::wsprintf(awText, g_localeData[m_nLanguage].pwAnalyzing[2], nNewPercent);
               else
                  ::wsprintf(awText, g_localeData[m_nLanguage].pwAnalyzing[3], m_nCurrentNumber+1, (int)m_inputFileList.size(), nNewPercent);
            }
            else
            {  
               if((int)m_inputFileList.size() == 1)
                  ::wsprintf(awText, g_localeData[m_nLanguage].pwConverting[2], nNewPercent);
               else
                  ::wsprintf(awText, g_localeData[m_nLanguage].pwConverting[3], m_nCurrentNumber+1, (int)m_inputFileList.size(), nNewPercent);
            }

            ::SetWindowText(hWnd, awText);
            m_nCurrentPercent = nNewPercent;
         }
      }
      else
      {  

         if( (m_convertData.nGainMode == GAIN_NORMALIZE || m_convertData.nGainMode == GAIN_AUTOMAXIMIZE) && m_convertData.nPass == 1)
         {  
            if((int)m_inputFileList.size() == 1)
               ::wsprintf(awText, g_localeData[m_nLanguage].pwAnalyzing[0]);
            else
               ::wsprintf(awText, g_localeData[m_nLanguage].pwAnalyzing[1], m_nCurrentNumber+1, (int)m_inputFileList.size());
            }
            else
            {  

            if((int)m_inputFileList.size() == 1)
               ::lstrcpy(awText, g_localeData[m_nLanguage].pwConverting[0]);
            else
               ::wsprintf(awText, g_localeData[m_nLanguage].pwConverting[1], m_nCurrentNumber+1, (int)m_inputFileList.size());
         }

         for(int j=0;j<m_nCurrentPercent;j++)
            ::lstrcat(awText, L".");

         ::SetWindowText(hWnd, awText);

         m_nCurrentPercent++;
         if(m_nCurrentPercent > 3)
            m_nCurrentPercent = 0;
      }
   }
   else
   {  

      if((int)m_inputFileList.size() == 1)
         ::lstrcpy(awText, g_localeData[m_nLanguage].pwExtracting[0]);
      else
         ::wsprintf(awText, g_localeData[m_nLanguage].pwExtracting[1], m_nCurrentNumber+1, (int)m_inputFileList.size());

      for(int j=0;j<m_nCurrentPercent;j++)
         ::lstrcat(awText, L".");

      ::SetWindowText(hWnd, awText);

      m_nCurrentPercent++;
      if(m_nCurrentPercent > 3)
         m_nCurrentPercent = 0;
   }
}
void CConvertDialog::ConvertExit(HWND hWnd)
{  

   ::KillTimer(hWnd, TIMER_GETINPUTFILENAME);
   ::KillTimer(hWnd, TIMER_CONVERT);
   ::KillTimer(hWnd, TIMER_GETPERCENT);

   m_pDirectShow->Release();

   if(m_convertData.nContainerType == 1 && m_convertData.nPass == 2)
   {  

      if(m_pi.hProcess != NULL)
      {  

         ::TerminateProcess(m_pi.hProcess, 0);
         ::WaitForSingleObject(m_pi.hProcess, 500);
         ::CloseHandle(m_pi.hProcess);
         m_pi.hProcess = NULL;
      }

      if(m_convertData.bDirectNeroAacEnc == false)
      {  
         if(::PathFileExists(m_awCurrentOutputFileName) != FALSE)
            ::DeleteFile(m_awCurrentOutputFileName);
      }

      ::PathRenameExtension(m_awCurrentOutputFileName, L".m4a");
      if(::PathFileExists(m_awCurrentOutputFileName) != FALSE)
         ::DeleteFile(m_awCurrentOutputFileName);
   }
   else
   {
      if(::PathFileExists(m_awCurrentOutputFileName) != FALSE)
         ::DeleteFile(m_awCurrentOutputFileName);
   }


}
void CConvertDialog::ConvertEnd(HWND hWnd, int nEndState)
{
   WCHAR awText[MAX_PATH];
   double dPeak = 1.0;
   double dGain = 0.0;

   if(m_convertData.nGainMode != 0 && m_convertData.nPass == 1)
   {  
      double dNormalize;

      m_pDirectShow->GetReplaygainResult(&dPeak, &dGain);

      dGain = dGain + (m_convertData.dGain - 89.0);

      dNormalize = ::pow(10.0, dGain / 20.0);

      if(m_convertData.nGainMode == GAIN_NORMALIZE)
      {  
         m_convertData.dNormalize = dNormalize;
      }
      else if(m_convertData.nGainMode == GAIN_AUTOMAXIMIZE)
      {  
         if(m_nCurrentNumber == 0)
         {  
            m_convertData.dNormalize = dNormalize;
         }
         else
         {  
            if(dNormalize < m_convertData.dNormalize)
               m_convertData.dNormalize = dNormalize;
         }
      }
   }

   m_pDirectShow->Release();

   if(nEndState == EC_COMPLETE)
   {  

      if(m_convertData.nContainerType == 1 && m_convertData.nPass == 2)
      {  

      }
      else if(m_convertData.nContainerType < 5)
      {  

         if(m_convertData.nGainMode == GAIN_ALBUMGAIN && m_convertData.nPass == 2)
         {

         }
         else if( (m_convertData.nGainMode == GAIN_NORMALIZE || m_convertData.nGainMode == GAIN_AUTOMAXIMIZE) && m_convertData.nPass == 1)
         {  
            if((int)m_inputFileList.size() == 1)
               ::wsprintf(awText, g_localeData[m_nLanguage].pwAnalyzing[2], 100);
            else
               ::wsprintf(awText, g_localeData[m_nLanguage].pwAnalyzing[3], m_nCurrentNumber+1, (int)m_inputFileList.size(), 100);

            ::SetWindowText(hWnd, awText);
            DoEvents(hWnd);
         }
         else
         {  
            if((int)m_inputFileList.size() == 1)
               ::wsprintf(awText, g_localeData[m_nLanguage].pwConverting[2], 100);
            else
               ::wsprintf(awText, g_localeData[m_nLanguage].pwConverting[3], m_nCurrentNumber+1, (int)m_inputFileList.size(), 100);

            ::SetWindowText(hWnd, awText);
            DoEvents(hWnd);
         }

         if(m_convertData.nGainMode == GAIN_TRACKGAIN)
         {  

            CReplayGain replayGain;

            switch(m_convertData.nContainerType)
            {
            case 0:  
               replayGain.WriteWav(m_awCurrentOutputFileName, GAIN_TRACKGAIN, dPeak, dGain);
               break;
            case 1:  
               break;
            case 2:  
               replayGain.WriteFraunhofer(m_awCurrentOutputFileName, GAIN_TRACKGAIN, 0.0, 0.0, dPeak, dGain);
               break;
            case 3:  
               replayGain.WriteLame(m_awCurrentOutputFileName, GAIN_TRACKGAIN, 0.0, 0.0, dPeak, dGain);
               break;
            case 4:  
               replayGain.WriteOgg(m_awCurrentOutputFileName, GAIN_TRACKGAIN, dPeak, dGain);
               break;
            }
         }
         else if(m_convertData.nGainMode == GAIN_ALBUMGAIN)
         {  

            if(m_convertData.nPass == 1)
            {
               if(m_nCurrentNumber == 0)
               {  
                  m_dAlbumGain = dGain;
                  m_dAlbumPeak = dPeak;
               }
               else
               {  
                  if(m_dAlbumGain < dGain)
                     m_dAlbumGain = dGain;

                  if(m_dAlbumPeak < dPeak)
                     m_dAlbumPeak = dPeak;
               }

               CReplayGain replayGain;

               switch(m_convertData.nContainerType)
               {
               case 0:  
                  replayGain.WriteWav(m_awCurrentOutputFileName, GAIN_TRACKGAIN, dPeak, dGain);
                  break;
               case 1:  
                  break;
               case 2:  
                  replayGain.WriteFraunhofer(m_awCurrentOutputFileName, GAIN_ALBUMGAIN, 0.0, 0.0, dPeak, dGain);
                  break;
               case 3:  
                  replayGain.WriteLame(m_awCurrentOutputFileName, GAIN_ALBUMGAIN, 0.0, 0.0, dPeak, dGain);
                  break;
               case 4:  
                  replayGain.WriteOgg(m_awCurrentOutputFileName, GAIN_TRACKGAIN, dPeak, dGain);
                  break;
               }
            }
            else
            {  

               CReplayGain replayGain;

               switch(m_convertData.nContainerType)
               {
               case 0:  
                  replayGain.WriteWav(m_awCurrentOutputFileName, GAIN_ALBUMGAIN, m_dAlbumPeak, m_dAlbumGain);
                  break;
               case 1:  
                  break;
               case 2:  
                  replayGain.OverWriteMp3AlbumGain(m_awCurrentOutputFileName, m_dAlbumPeak, m_dAlbumGain);
                  break;
               case 3:  
                  replayGain.OverWriteMp3AlbumGain(m_awCurrentOutputFileName, m_dAlbumPeak, m_dAlbumGain);
                  break;
               case 4:  
                  replayGain.WriteOgg(m_awCurrentOutputFileName, GAIN_ALBUMGAIN, m_dAlbumPeak, m_dAlbumGain);
                  break;
               }
            }
         }
      }
   }
   else
   {  

      m_nErrorCount++;

      if(::PathFileExists(m_awCurrentOutputFileName) != FALSE)
         ::DeleteFile(m_awCurrentOutputFileName);
   }

   if( (m_convertData.nGainMode == GAIN_NORMALIZE || m_convertData.nGainMode == GAIN_AUTOMAXIMIZE) && m_convertData.nPass == 1)
   {  
      if(::PathFileExists(m_awCurrentOutputFileName) != FALSE)
         ::DeleteFile(m_awCurrentOutputFileName);
   }

   if(m_convertData.nContainerType == 1 && m_convertData.bDirectNeroAacEnc == false && m_convertData.nPass == 2)
   {  
      if(::PathFileExists(m_awTmpFileName) != FALSE)
         ::DeleteFile(m_awTmpFileName);
   }

   if(m_convertData.nContainerType == 1 || m_convertData.nGainMode == GAIN_NORMALIZE)
   {  
      if(m_convertData.nPass == 1)
      {  
         m_convertData.nPass = 2;
      }
      else
      {  
         m_convertData.nPass = 1;
         m_nCurrentNumber++;
      }
   }
   else
   {  
      m_nCurrentNumber++;
   }

   ::wsprintf(awText, g_localeData[m_nLanguage].pwResult, m_nCurrentNumber - m_nErrorCount, m_nErrorCount);
   ::SetDlgItemText(hWnd, IDC_STATIC_CONVERT_RESULT, awText);
   ::InvalidateRect(hWnd, NULL, TRUE);
   DoEvents(hWnd);

   if(m_nCurrentNumber < (int)m_inputFileList.size())
   {  


      ::SetTimer(hWnd, TIMER_CONVERT, 200, NULL); 
   }
   else
   {  
      if(m_nErrorCount < (int)m_inputFileList.size())
      {
         if(m_convertData.nGainMode == GAIN_AUTOMAXIMIZE && m_convertData.nPass == 1)
         {  
            m_convertData.nPass = 2;
            m_nCurrentNumber = 0;

            ::SetTimer(hWnd, TIMER_CONVERT, 55, NULL);
         }
         else if(m_convertData.nGainMode == GAIN_ALBUMGAIN && m_convertData.nPass == 1)
         {  
            m_convertData.nPass = 2;
            m_nCurrentNumber = 0;

            ::SetDlgItemText(hWnd, IDC_STATIC_CONVERT_FILENAME, L"-");
            ::SetDlgItemText(hWnd, IDC_STATIC_CONVERT_INPUT_FORMAT, L"-");
            ::SetDlgItemText(hWnd, IDC_STATIC_CONVERT_OUTPUT_FORMAT, L"-");

            ::SetTimer(hWnd, TIMER_CONVERT, 55, NULL);
         }
         else
         {  

            ::PlaySound(MAKEINTRESOURCE(IDR_WAVE), ::GetModuleHandle(NULL), SND_RESOURCE|SND_ASYNC);

            for (int i=0;i<4;i++)
            {
               DoEvents(hWnd);
               ::FlashWindow(hWnd, TRUE);
               ::Sleep(500);
               DoEvents(hWnd);
               ::FlashWindow(hWnd, FALSE);
               DoEvents(hWnd);
            }

            m_bExit = true;
            EndDialog(hWnd);
            ::EndDialog(hWnd, IDOK);
         }
      }
      else
      {
         ::MessageBox(hWnd, g_localeData[m_nLanguage].error.pwConvert, L"EcoDecoTooL error", MB_OK);

         m_bExit = true;
         EndDialog(hWnd);
         ::EndDialog(hWnd, IDOK);
      }
   }
}
void CConvertDialog::Show(CONVERTDATA *pData, int nLanguage)
{
   m_nLanguage = nLanguage;

   m_convertData.nContainerType = pData->nContainerType;
   m_convertData.nOutputFolder  = pData->nOutputFolder;
   ::lstrcpy(m_convertData.awOutputFolder, pData->awOutputFolder);

   ::CopyMemory(&m_convertData.wf, &pData->wf, sizeof(m_convertData.wf));
   m_convertData.nEncodeMode = pData->nEncodeMode;
   m_convertData.nAdvancedMode = pData->nAdvancedMode;
   m_convertData.nABRCBR = pData->nABRCBR;
   m_convertData.nVBR = pData->nVBR;
   m_convertData.fVBR = pData->fVBR;
   m_convertData.nPass = pData->nPass;
   m_convertData.nGainMode = pData->nGainMode;
   m_convertData.dGain = pData->dGain;

   m_convertData.dropList.clear();
   for(int i=0;i<(int)pData->dropList.size();i++)
      m_convertData.dropList.push_back(pData->dropList[i]);



   ::DialogBox(::GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_DIALOG_CONVERT_JAPANESE), NULL, (DLGPROC)DialogProc);
}
void CConvertDialog::InitDialog(HWND hWnd)
{
   WCHAR awIniFileName[MAX_PATH];
   ::GetModuleFileName(NULL, awIniFileName, MAX_PATH);
   ::PathRemoveFileSpec(awIniFileName);
   ::lstrcat(awIniFileName, TEXT("\\EcoDecoTooL.ini"));

   RECT r1, r2;
   POINT p;

   m_nCurrentCpuUsage = (int)::GetPrivateProfileInt(TEXT("Setting"), TEXT("ConvertWindowCPU"), 4, awIniFileName);
   if(m_nCurrentCpuUsage < 0 || 5 < m_nCurrentCpuUsage) m_nCurrentCpuUsage = 4;

   for(int i=0;i<5;i++)
      ::SendMessage(::GetDlgItem(hWnd, IDC_COMBO_CPU), CB_ADDSTRING, 0, (LPARAM)g_localeData[m_nLanguage].pwCpuUsage[i]);

   ::SendMessage(::GetDlgItem(hWnd, IDC_COMBO_CPU), CB_SETCURSEL, (WPARAM)m_nCurrentCpuUsage, (LPARAM)0);

   p.x = (int)::GetPrivateProfileInt(TEXT("Setting"), TEXT("ConvertWindowLeft"), -10, awIniFileName);
   p.y = (int)::GetPrivateProfileInt(TEXT("Setting"), TEXT("ConvertWindowTop"), -10, awIniFileName);

   if(p.x == -10 && p.y == -10)
   {  

      p.x = (int)::GetPrivateProfileInt(TEXT("Setting"), TEXT("MainWindowLeft"), 100, awIniFileName);
      p.y = (int)::GetPrivateProfileInt(TEXT("Setting"), TEXT("MainWindowTop"), 100, awIniFileName);
      p.y += 220;
   }

   ::SystemParametersInfo(SPI_GETWORKAREA, 0, &r1, 0);
   ::GetWindowRect(hWnd, &r2);

   if(p.x < 0)
      p.x = 0;
   else if( ((r1.right- r1.left) - (r2.right - r2.left)) < p.x)
      p.x = (r1.right- r1.left) - (r2.right - r2.left);

   if(p.y < 0)
      p.y = 0;
   else if( ((r1.bottom- r1.top) - (r2.bottom - r2.top)) < p.y)
      p.y = (r1.bottom- r1.top) - (r2.bottom - r2.top);

   ::SetWindowPos(hWnd, HWND_TOPMOST, p.x, p.y, 0, 0, SWP_NOSIZE);
   ::SetForegroundWindow(hWnd);
   ::UpdateWindow(hWnd);
   ::SetWindowPos(hWnd, HWND_NOTOPMOST, p.x, p.y, 0, 0, SWP_NOSIZE);
   ::UpdateWindow(hWnd);
   ::InvalidateRect(hWnd, NULL, TRUE);
   DoEvents(hWnd);

   GetInputFileName(hWnd);

   if(this->m_inputFileList.size() == 0)
   {  
      ::MessageBox(hWnd, g_localeData[m_nLanguage].error.pwDropFile, L"EcoDecoTooL error", MB_OK);
      ::EndDialog(hWnd, IDOK);
      return;
   }

   WCHAR awText[MAX_PATH];
   ::wsprintf(awText, g_localeData[m_nLanguage].pwResult, 0, 0);
   ::SetDlgItemText(hWnd, IDC_STATIC_CONVERT_RESULT, awText);
   ::SetDlgItemText(hWnd, IDC_STATIC_CONVERT_FILENAME, TEXT(""));
   ::InvalidateRect(hWnd, NULL, TRUE);
   DoEvents(hWnd);

   if(m_convertData.nContainerType == 5)
   {  
      ::SetDlgItemText(hWnd, IDC_STATIC_INPUT, g_localeData[m_nLanguage].pwRawInput);
      ::SetDlgItemText(hWnd, IDC_STATIC_OUTPUT, L"");
      ::SetDlgItemText(hWnd, IDC_STATIC_CONVERT_OUTPUT_FORMAT, L"");
   }

   m_convertData.nPass = 1;
   ::SetTimer(hWnd, TIMER_CONVERT, 55, NULL);
}
void CConvertDialog::EndDialog(HWND hWnd)
{
   if(m_bExit == false)
   {
      m_bExit = true;
      ::Sleep(500);
   }
   WCHAR awText[MAX_PATH], awIniFileName[MAX_PATH];

   ::GetModuleFileName(NULL, awIniFileName, MAX_PATH);
   ::PathRemoveFileSpec(awIniFileName);
   ::lstrcat(awIniFileName, TEXT("\\EcoDecoTooL.ini"));

   WINDOWPLACEMENT wndpl;
   ::GetWindowPlacement(hWnd, &wndpl);
   ::wsprintf(awText, TEXT("%d"), wndpl.rcNormalPosition.left);
   ::WritePrivateProfileString(TEXT("Setting"), TEXT("ConvertWindowLeft"), awText, awIniFileName);
   ::wsprintf(awText, TEXT("%d"), wndpl.rcNormalPosition.top);
   ::WritePrivateProfileString(TEXT("Setting"), TEXT("ConvertWindowTop"), awText, awIniFileName);

   int nCpuUsage = ::SendMessage(::GetDlgItem(hWnd, IDC_COMBO_CPU), CB_GETCURSEL, (WPARAM)0, (LPARAM)0);
   ::wsprintf(awText, TEXT("%d"), nCpuUsage);
   ::WritePrivateProfileString(TEXT("Setting"), TEXT("ConvertWindowCPU"), awText, awIniFileName);
}
LRESULT CALLBACK CConvertDialog::DialogProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
   switch (msg)
   {
   case WM_INITDIALOG:
      g_pMyClass->InitDialog(hWnd);
      return TRUE;

   case WM_CTLCOLORSTATIC:
      ::SetBkMode((HDC)wParam, TRANSPARENT);
      return (BOOL)(HBRUSH)GetStockObject(NULL_BRUSH);

   case WM_COMMAND:
      switch(LOWORD(wParam))
      {
      case IDC_COMBO_CPU:
         g_pMyClass->m_nNewCpuUsage = ::SendMessage(::GetDlgItem(hWnd, IDC_COMBO_CPU), CB_GETCURSEL, (WPARAM)0, (LPARAM)0);
         return TRUE;
      }

      break;

   case WM_CONVERT:
      g_pMyClass->Convert(hWnd);
      return TRUE;

   case WM_GRAPHNOTIFY:

      switch(g_pMyClass->m_pDirectShow->PlayEnd())
      {
      case EC_COMPLETE:
         g_pMyClass->m_nConvertState = EC_COMPLETE;
         return TRUE;
      case EC_ERRORABORT:
         g_pMyClass->m_nConvertState= EC_ERRORABORT;
         return TRUE;
      }

      return FALSE;

   case WM_TIMER:

      switch(wParam)
      {
      case TIMER_GETINPUTFILENAME:

         ::KillTimer(hWnd, TIMER_GETINPUTFILENAME);
         g_pMyClass->GetInputFileName(hWnd);

         break;
      case TIMER_CONVERT:

         ::KillTimer(hWnd, TIMER_CONVERT);
         g_pMyClass->Convert(hWnd);

         break;
      case TIMER_GETPERCENT:

         if(g_pMyClass->m_nConvertState == EC_COMPLETE || g_pMyClass->m_nConvertState == EC_ERRORABORT)
         {  

            ::KillTimer(hWnd, TIMER_GETPERCENT);
            g_pMyClass->ConvertEnd(hWnd, g_pMyClass->m_nConvertState);
         }
         else
            g_pMyClass->ConvertGetPercent(hWnd);

         break;
      }

      return TRUE;

   case WM_CTLCOLORDLG:
      ::SetBkMode((HDC)wParam, OPAQUE);
      return (LRESULT)::GetStockObject(WHITE_BRUSH);

   case WM_DESTROY:
      ::PostQuitMessage(0); 
      return TRUE;

   case WM_CLOSE:
      g_pMyClass->ConvertExit(hWnd);
      g_pMyClass->EndDialog(hWnd);
      ::EndDialog(hWnd ,IDCANCEL);
      return TRUE;
   }

	return FALSE;
}
