/********************************************************************
 *                                                                  *
 * THIS FILE IS PART OF THE FILEWRITERDX 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 "aoTuvWriter.h"
#include "DShowTool.h"

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

// strmbase.libは、各自で用意してください
#pragma comment(lib, "strmbase.lib")
#pragma comment(lib, "lib/DShowTool.lib")
#pragma comment(lib, "lib/aoTuvWriter.lib")
#pragma comment(lib, "lib/ogg_static.lib")
#pragma comment(lib, "lib/vorbis_static.lib")
#pragma comment(lib, "lib/vorbisenc_static.lib")

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


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

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

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

   QzCComPtr<IBaseFilter> paoTuvWriter = NULL;
   CaoTuvWriter *pCTR = NULL;

   ::CoInitialize(NULL);

   if(argc != 3)
   {
		puts("\naoTuvenc.exe <name1> <name2>\n");
		puts("\tname1 : source wav file name\n");
		puts("\tname2 : output oggvorbis 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) goto end;

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

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

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

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

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

   // ソースフィルタとaoTuvWriterフィルタを繋ぐ
   hr = dshowTool.Connect(pGraphBuilder, pSourceFilter, paoTuvWriter);
   if(FAILED(hr)) goto end;

   // エンコード設定をする
   VORBISFORMAT vorbisFormat;

   // ABRでエンコードする場合
   // 設定可能値：8000〜320000 
/*
   vorbisFormat.fQuality = -1.0f;
   vorbisFormat.nMinBitsPerSec =  32000;  //  32kbps
   vorbisFormat.nAvgBitsPerSec = 128000;  // 128kbps
   vorbisFormat.nMaxBitsPerSec = 196000;  // 196kbps
*/

   // CBRでエンコードする場合
   // 設定可能値：8000〜320000 
/*
   vorbisFormat.fQuality = -1.0f;
   vorbisFormat.nMinBitsPerSec = -1;
   vorbisFormat.nAvgBitsPerSec = 128000;  // 128kbps
   vorbisFormat.nMaxBitsPerSec = -1;
*/

   // VBRでエンコードする場合
   vorbisFormat.fQuality = -0.1f;      // 範囲は-0.1f〜1.0fで、0.1刻み。値が大きいほどビットレートが高くなる
   vorbisFormat.nMinBitsPerSec = -1;
   vorbisFormat.nAvgBitsPerSec = -1;
   vorbisFormat.nMaxBitsPerSec = -1;

   hr = pCTR->SetVorbisFormat((void *)&vorbisFormat);
   if(FAILED(hr))
   {
      puts("\noggvorvis init failed.\n");
      goto end;
   }

   // タグを挿入する場合
/*
   VORBISTAG vorbisTag;
   // 初期化を忘れずに行ってください
   ::ZeroMemory(&vorbisTag, sizeof(VORBISTAG));

   ::lstrcpyA(vorbisTag.acTitle, "サンプル曲");
   ::lstrcpyA(vorbisTag.acArtist, "sample");

   pCTR->SetVorbisTag((void *)&vorbisTag);
*/


   // 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(pGraphBuilder);

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

   ::CoUninitialize();

  return(0);
}
