/********************************************************************
 *                                                                  *
 * THIS FILE IS PART OF THE FILEWRITEREX EXAMPLE SOURCE CODE.       *
 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
 *                                                                  *
 * THE FILEWRITERDX SOURCE CODE IS (C) COPYRIGHT 2008 Cocha         *
 * http://sourceforge.jp/projects/directshow/                       *
 *                                                                  *
 * THE DShowTool SOURCE CODE IS (C) COPYRIGHT 2008 Cocha            *
 * http://sourceforge.jp/projects/directshow/                       *
 *                                                                  *
 ********************************************************************/

#define WIN32_LEAN_AND_MEAN

#include <windows.h>
#include <stdio.h>
#include <shlwapi.h>
#include <streams.h>

#include "FileWriterDX.h"
#include "DShowTool.h"

#define SAFE_RELEASE(p) { if(p!=NULL) { (p)->Release(); (p)=NULL; } }

// strmbase.libは、各自で用意してください
// 以下のlibは、リリースビルド用です
#pragma comment(lib, "strmbase.lib")
#pragma comment(lib, "DShowTool.lib")
#pragma comment(lib, "FileWriterDX.lib")

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


static const GUID CLSID_MP3DecodeFilter = 
{ 0x38BE3000, 0xDBF4, 0x11D0, { 0x86, 0x0E, 0x00, 0xA0, 0x24, 0xCF, 0xEF, 0x6D } };


int main(int argc, char **argv)
{
   // mp3→wav変換 サンプルプログラム

   HRESULT hr;
   CDShowTool dshowTool;
   IGraphBuilder *pGraphBuilder = NULL;
   IMediaEventEx *pMediaEventEx = NULL;
   IMediaControl *pMediaControl = NULL;

   WCHAR awInputFileName[MAX_PATH], awOutputFileName[MAX_PATH];
   IBaseFilter *pSourceFilter = NULL;
   IBaseFilter *pMP3DecodeFilter = NULL;

   QzCComPtr<IBaseFilter> pFileWriter = NULL;
   CFileWriterDX *pCTR = NULL;

   ::CoInitialize(NULL);

   if(argc != 3)
   {
		puts("\nmp3dec.exe <name1> <name2>\n");
		puts("\tname1 : source mp3 file name\n");
		puts("\tname2 : output wav file name\n");
      return(0);
   }

   // コマンドライン引数をWCHAR型に変換
   MultiByteToWideChar(CP_ACP, 0, argv[1], -1, awInputFileName, sizeof(awInputFileName));
   MultiByteToWideChar(CP_ACP, 0, argv[2], -1, awOutputFileName, sizeof(awOutputFileName));

   // 入力ファイルの存在チェック
   if(::PathFileExists(awInputFileName) == FALSE)
   {
		puts("\ncan't find source wav file\n");
      return(0);
   }

   // pGraphBuilderを作成する
   ::CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGraphBuilder);
   if(pGraphBuilder == NULL)
   {
		puts("\ncan't find source wav file\n");
      return(0);
   }

   // ソースフィルタを登録する
   pSourceFilter = dshowTool.AddSourceFilter(pGraphBuilder, CLSID_AsyncReader, awInputFileName);
   if(pSourceFilter == NULL) goto end;

   // MP3デコードフィルタを登録する
   pMP3DecodeFilter = dshowTool.AddFilter(pGraphBuilder, CLSID_MP3DecodeFilter);
   if(pMP3DecodeFilter == NULL) goto end;

   // FileWriterを登録する
   pCTR = new CFileWriterDX(NULL, &hr);
   if(FAILED(hr) || pCTR == NULL) goto end;

   pFileWriter = pCTR;
   hr = pGraphBuilder->AddFilter((IBaseFilter *)pFileWriter, NULL);
   if(FAILED(hr)) goto end;

   // 出力ファイル名を指定する
   IFileSourceFilter *pFileSinkFilter = NULL;
   pFileWriter->QueryInterface(IID_IFileSinkFilter, (void**)&pFileSinkFilter);
   if(pFileSinkFilter == NULL) goto end;

   hr = pFileSinkFilter->Load(awOutputFileName, NULL);
   SAFE_RELEASE(pFileSinkFilter);
   if(FAILED(hr)) goto end;

   // ソースフィルタとMP3デコードフィルタを繋ぐ
   hr = dshowTool.Connect(pGraphBuilder, pSourceFilter, pMP3DecodeFilter);
   if(FAILED(hr)) goto end;

   // MP3デコードフィルタとFileWriterを繋ぐ
   hr = dshowTool.ConnectDirect(pGraphBuilder, pMP3DecodeFilter, pFileWriter, NULL);
   if(FAILED(hr)) goto end;

   // pMediaEventExの準備
   pGraphBuilder->QueryInterface(IID_IMediaEventEx, (void **)&pMediaEventEx);
   if(pMediaEventEx == NULL) goto end;

   // pMediaControlの準備
   pGraphBuilder->QueryInterface(IID_IMediaControl, (void **)&pMediaControl);
   if(pMediaControl == NULL) goto end;

   // 再生する
   hr = pMediaControl->Run();
   if(hr != NO_ERROR) goto end;

   puts("file writing...\n");

   // デコード終了まで待つ
   long eventCode;
   pMediaEventEx->WaitForCompletion(INFINITE, &eventCode);

   puts("decode end.\n");

end:

   if(pMediaControl != NULL)
   {
      pMediaControl->Stop();
      SAFE_RELEASE(pMediaControl);
   }

   SAFE_RELEASE(pMediaEventEx);
   SAFE_RELEASE(pSourceFilter);
   SAFE_RELEASE(pMP3DecodeFilter);
   SAFE_RELEASE(pGraphBuilder);

   // pFileWriterを手動でReleaseしないで下さい。
   // pGraphBuilderをReleaseした時に自動でpFileWriterもReleaseされます。

   ::CoUninitialize();

  return(0);
}
