/********************************************************************
 *                                                                  *
 * THIS FILE IS PART OF THE aoTuvWriter 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 OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2007             *
 * by the Xiph.Org Foundation http://www.xiph.org/                  *
 *                                                                  *
 * THE aoTuv SOURCE CODE IS (C) COPYRIGHT 2003-2008 Aoyumi          *
 * http://www.geocities.jp/aoyoume/aotuv/                           *
 *                                                                  *
 * THE aoTuvWriter SOURCE CODE IS (C) COPYRIGHT 2008 Cocha          *
 * http://sourceforge.jp/projects/directshow/                       *
 *                                                                  *
 ********************************************************************/

#ifndef _aoTuvWriter_h_
#define _aoTuvWriter_h_

#include <windows.h>
#include <shlwapi.h>
#include <time.h>
#include <streams.h>
#include "include/vorbisenc.h"

#define ENCODE_BUFFER_SIZE 32768
#define FILTER_NAME L"aoTuv Writer"

// {BCA97B10-FF13-4818-ACB7-C279DF3A55FF}
static const GUID CLSID_aoTuvWriter =
{ 0xbca97b10, 0xff13, 0x4818, { 0xac, 0xb7, 0xc2, 0x79, 0xdf, 0x3a, 0x55, 0xff } };


typedef struct tagVORBISFORMAT
{
	WORD  nChannels;
	long  nSamplesPerSec;
	long  nMinBitsPerSec;
	long  nAvgBitsPerSec;
	long  nMaxBitsPerSec;
	float fQuality;
} VORBISFORMAT;

typedef struct tagVORBISTAG
{
   char acTitle[256];
   char acArtist[256];
   char acAlbum[256];
   char acTrackNumber[256];
   char acDate[256];
   char acGenre[256];
   char acComment[256];
} VORBISTAG;

// ------------------------------------------------------------------------------------------------------------------------
class CaoTuvEncode
{
public:

   // コンストラクタとデストラクタ
   CaoTuvEncode();
   ~CaoTuvEncode();

   // ユーザ関数
   HRESULT EncodeInit(WCHAR *, VORBISFORMAT *, VORBISTAG *);
   HRESULT Encode(int);
   HRESULT Receive(short *, int);
   HRESULT EncodeEnd();
   HRESULT SetFileName(WCHAR *);

private:

   // ユーザ関数
   void SJIStoUTF8(char *, int);

   // 使用変数
   ogg_stream_state m_os;
   ogg_page         m_og;
   ogg_packet       m_op;
   vorbis_info      m_vi;
   vorbis_comment   m_vc;
   vorbis_dsp_state m_vd;
   vorbis_block     m_vb;

   HANDLE m_hFile;
   int m_nChannels;
};
// ------------------------------------------------------------------------------------------------------------------------
class CInputPin : public CRenderedInputPin
{
   friend class CaoTuvEncode;
   friend class CaoTuvWriter;

public:

   // コンストラクタとデストラクタ
   CInputPin(CaoTuvWriter *, LPUNKNOWN, CCritSec *, CCritSec *, HRESULT *);
   ~CInputPin();

   // CRenderedInputPin(CBasePin)の純粋仮想メソッド
   virtual HRESULT CheckMediaType(const CMediaType *);

   // CRenderedInputPinのオーバーライド
   STDMETHODIMP Receive(IMediaSample *);
   STDMETHODIMP EndOfStream(void);
   HRESULT Stop();
   STDMETHODIMP ReceiveCanBlock() { return S_FALSE;}
   HRESULT BreakConnect();
   HRESULT Run(REFERENCE_TIME);

   STDMETHODIMP NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
   {
      m_tLast = 0;
      return S_OK;
   }

   // ユーザ関数
   HRESULT SetVorbisFormat(VORBISFORMAT *);
   HRESULT SetVorbisTag(VORBISTAG *);
   HRESULT SetFileName(LPCOLESTR);

private:

   // 使用変数
   CaoTuvWriter * const m_pFilter;
   CCritSec *m_pReceiveLock;
   REFERENCE_TIME m_tLast;
   WAVEFORMATEX m_InputWaveFormatEx;
   CaoTuvEncode *paoTuvEncode;
   WCHAR m_awFileName[MAX_PATH];
   VORBISFORMAT m_VorbisFormat;
   VORBISTAG m_VorbisTag;
};
// ------------------------------------------------------------------------------------------------------------------------
class CaoTuvWriter : public CBaseFilter, public IFileSinkFilter
{
   friend class CInputPin;

public:
   DECLARE_IUNKNOWN

   // コンストラクタとデストラクタ
   CaoTuvWriter(LPUNKNOWN,HRESULT *);
   ~CaoTuvWriter();

   // CBaseFilterの純粋仮想メソッド
   virtual CBasePin *GetPin(int n);
   virtual int GetPinCount();

   // CBaseFilterのオーバーライド
   STDMETHODIMP NonDelegatingQueryInterface(REFIID, void **);

   // IFileSinkFilterのオーバーライド
   STDMETHODIMP SetFileName(LPCOLESTR, const AM_MEDIA_TYPE *);
   STDMETHODIMP GetCurFile(LPOLESTR *, AM_MEDIA_TYPE *);

   // ユーザ関数
   HRESULT SetVorbisFormat(void *);
   HRESULT SetVorbisTag(void *);

private:

   // 使用変数
   CCritSec m_Lock;
   CCritSec m_ReceiveLock;
   CInputPin *m_pInputPin;
   CPosPassThru *m_pPosition;
   WCHAR m_awFileName[MAX_PATH];
};
// ------------------------------------------------------------------------------------------------------------------------

#endif _aoTuvWriter_h_
