/********************************************************************
 *                                                                  *
 * 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/                       *
 *                                                                  *
 ********************************************************************/

#include "aoTuvWriter.h"

// ------------------------------------------------------------------------------------------------------------------------
STDMETHODIMP CInputPin::Receive(IMediaSample *pSample)
{
   HRESULT hr;

   CheckPointer(pSample, E_POINTER);
   CAutoLock lock(m_pReceiveLock);

   REFERENCE_TIME tStart, tStop;
   pSample->GetTime(&tStart, &tStop);

   m_tLast = tStart;

   BYTE *pbData;
   hr = pSample->GetPointer(&pbData);
   if(FAILED(hr))
      return hr;

   hr = paoTuvEncode->Receive((short *)pbData, pSample->GetActualDataLength() / 2);

   return hr;
}
// ------------------------------------------------------------------------------------------------------------------------
STDMETHODIMP CInputPin::EndOfStream(void)
{  // もう受け取るデータが無くなった場合に呼ばれる

   CAutoLock lock(m_pReceiveLock);
   CAutoLock cObjectLock(m_pLock);

   if(paoTuvEncode == NULL)
      return E_FAIL;

   paoTuvEncode->EncodeEnd();

   return CRenderedInputPin::EndOfStream();
}
// ------------------------------------------------------------------------------------------------------------------------
HRESULT CInputPin::Run(REFERENCE_TIME tStart)
{  // フィルタが実行された場合に呼ばれる

   CAutoLock lock(m_pReceiveLock);
   CAutoLock cObjectLock(m_pLock);

   // すでにファイルが存在するなら、ファイルを削除する
   if(::PathFileExists(m_awFileName) != FALSE)
   {
      if(::DeleteFile(m_awFileName) == FALSE)
         return E_FAIL; // ファイル削除に失敗
   }

   m_VorbisFormat.nChannels = m_InputWaveFormatEx.nChannels;
   m_VorbisFormat.nSamplesPerSec = m_InputWaveFormatEx.nSamplesPerSec;

   HRESULT hr;
   hr = paoTuvEncode->EncodeInit(m_awFileName, &m_VorbisFormat, &m_VorbisTag);
   if(FAILED(hr))
      return hr;

   return S_OK;
}
// ------------------------------------------------------------------------------------------------------------------------
HRESULT CInputPin::Stop()
{  // 停止ボタンが押された場合に呼ばれる

   CAutoLock lock(m_pReceiveLock);
   CAutoLock cObjectLock(m_pLock);

   if(paoTuvEncode == NULL)
      return E_FAIL;

   paoTuvEncode->EncodeEnd();

   return S_OK;
}
// ------------------------------------------------------------------------------------------------------------------------
HRESULT CInputPin::CheckMediaType(const CMediaType *pMediaType)
{  // 入力ピンがほかのピンと繋がった時に呼ばれる

   CAutoLock lock(m_pReceiveLock);

   if(*pMediaType->Subtype() == MEDIASUBTYPE_PCM  &&  *pMediaType->FormatType() == FORMAT_WaveFormatEx)
   {
      if( ((WAVEFORMATEX *)pMediaType->Format())->wFormatTag != WAVE_FORMAT_PCM)
      {  // 無圧縮PCM以外なら受け付けない
         return S_FALSE;
      }

      if( ((WAVEFORMATEX *)pMediaType->Format())->wBitsPerSample != 16)
      {  // 16bit以外なら受け付けない
         return S_FALSE;
      }

      if( ((WAVEFORMATEX *)pMediaType->Format())->nSamplesPerSec > 48000)
      {   // サンプリング周波数が48kHzより大きいなら受け付けない
         return S_FALSE;
      }

      if( ((WAVEFORMATEX *)pMediaType->Format())->nChannels != 1 && ((WAVEFORMATEX *)pMediaType->Format())->nChannels != 2)
      {   // モノラルステレオ以外ならなら受け付けない
         return S_FALSE;
      }

      // 入力の音質を格納しておく
      ::CopyMemory(&m_InputWaveFormatEx, pMediaType->Format(), sizeof(WAVEFORMATEX));

      return S_OK;
   }

   return S_FALSE;
}
// -----------------------------------------------------------------------------------------------------------------------------------
HRESULT CInputPin::BreakConnect()
{
   if(m_pFilter->m_pPosition != NULL)
      m_pFilter->m_pPosition->ForceRefresh();

   return CRenderedInputPin::BreakConnect();
}
// -----------------------------------------------------------------------------------------------------------------------------------
HRESULT CInputPin::SetVorbisFormat(VORBISFORMAT *pVorbisFormat)
{
   // 設定を格納しておく
   ::CopyMemory(&m_VorbisFormat, pVorbisFormat, sizeof(VORBISFORMAT));

   return S_OK;
}
// -----------------------------------------------------------------------------------------------------------------------------------
HRESULT CInputPin::GetVorbisFormat(VORBISFORMAT *pVorbisFormat)
{  // エンコード設定を取得する

   ::CopyMemory(pVorbisFormat, &m_VorbisFormat, sizeof(VORBISFORMAT));
   return S_OK;
}
// -----------------------------------------------------------------------------------------------------------------------------------
HRESULT CInputPin::SetVorbisTag(VORBISTAG *pVorbisTag)
{
   // 設定を格納しておく
   ::CopyMemory(&m_VorbisTag, pVorbisTag, sizeof(VORBISTAG));

   return S_OK;
}
// -----------------------------------------------------------------------------------------------------------------------------------
HRESULT CInputPin::SetFileName(LPCOLESTR pszFileName)
{
   // ファイル名を格納しておく
   lstrcpyW(m_awFileName, pszFileName);

   return S_OK;
}
// -----------------------------------------------------------------------------------------------------------------------------------
CInputPin::CInputPin(CaoTuvWriter *pFilter, LPUNKNOWN pUnk, CCritSec *pLock, CCritSec *pReceiveLock, HRESULT *phr)
   : CRenderedInputPin(NAME("Input"), pFilter, pLock, phr, L"Input"), m_pReceiveLock(pReceiveLock), m_pFilter(pFilter), m_tLast(0)
{  // CInputPinのコンストラクタ

   paoTuvEncode = new CaoTuvEncode();

   // 変数の初期化
   ::ZeroMemory(m_awFileName, MAX_PATH);
   ::ZeroMemory(&m_VorbisFormat, sizeof(VORBISFORMAT));
   ::ZeroMemory(&m_VorbisTag, sizeof(VORBISTAG));

   m_VorbisFormat.fQuality = 0.4f;
   m_VorbisFormat.nMinBitsPerSec = -1;
   m_VorbisFormat.nAvgBitsPerSec = -1;
   m_VorbisFormat.nMaxBitsPerSec = -1;
}
// ------------------------------------------------------------------------------------------------------------------------
CInputPin::~CInputPin()
{  // CInputPinのデストラクタ

   if(paoTuvEncode != NULL)
      delete paoTuvEncode;
}
// ------------------------------------------------------------------------------------------------------------------------
