/**************************************************************************
 * 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 "CSimpleFilter.h"


CSimpleWriterInputPin::CSimpleWriterInputPin(CSimpleWriter *pFilter, LPUNKNOWN pUnk, CCritSec *pLock, CCritSec *pReceiveLock, HRESULT *phr)
   : CRenderedInputPin(NAME("Input"), pFilter, pLock, phr, L"Input") , m_pFilter(pFilter)
{  

   m_pLock = pLock;
}

CSimpleWriterInputPin::~CSimpleWriterInputPin()
{  

}

STDMETHODIMP CSimpleWriterInputPin::Receive(IMediaSample *pInSample)
{
   CAutoLock lck(m_pLock);

   if(m_pFilter->m_bFirstReceive == true)
   {
      m_pFilter->m_bFirstReceive = false;

      HRESULT hr;
      hr = m_pFilter->OnStart(m_pFilter->m_hFile);
      if(FAILED(hr))
         return hr;
   }

   return m_pFilter->OnReceive(m_pFilter->m_hFile, pInSample);
}

STDMETHODIMP CSimpleWriterInputPin::EndOfStream(void)
{  

   CAutoLock lck(m_pLock);

   m_pFilter->OnStop(m_pFilter->m_hFile, true);

   m_pFilter->m_bFirstReceive = true;

   return CRenderedInputPin::EndOfStream();
}

HRESULT CSimpleWriterInputPin::CheckMediaType(const CMediaType *pmtIn)
{  
   return m_pFilter->OnConnectInPin(pmtIn);
}

STDMETHODIMP CSimpleWriterInputPin::BeginFlush()
{  

   HRESULT hr = CRenderedInputPin::BeginFlush();

   CAutoLock lck(m_pLock);

   m_pFilter->OnSeek(m_pFilter->m_hFile);

   return hr;
}

HRESULT CSimpleWriterInputPin::BreakConnect()
{
   if(m_pFilter->m_pPosition != NULL)
      m_pFilter->m_pPosition->ForceRefresh();

   return CRenderedInputPin::BreakConnect();
}


CSimpleWriter::CSimpleWriter(__in_opt LPCTSTR pName, __inout_opt LPUNKNOWN pUnk, REFCLSID clsid, HRESULT *phr)
   : CBaseFilter(pName, pUnk, &m_ReceiveLock, clsid)
{  

   
   m_pPosition = NULL;
   m_hFile = NULL;
   m_bFirstReceive = true;
   ::ZeroMemory(m_awInputFileName, sizeof(m_awInputFileName));

   
   m_pInput = new CSimpleWriterInputPin(this, GetOwner(), &m_Lock, &m_ReceiveLock, phr);
   if (m_pInput == NULL)
   {
      if(phr != NULL)
         *phr = E_OUTOFMEMORY;

      return;
   }

   if(phr != NULL)
      *phr = S_OK;
}

CSimpleWriter::~CSimpleWriter()
{  

   
   if(m_hFile != NULL)
   {
      ::CloseHandle(m_hFile);
      m_hFile = NULL;
   }

   SAFE_DELETE(m_pInput);
   SAFE_DELETE(m_pPosition);
}

STDMETHODIMP CSimpleWriter::Stop()
{  
   CAutoLock lck(&m_Lock);

   OnStop(m_hFile, false);

   
   if(m_hFile != NULL)
   {
      ::CloseHandle(m_hFile);
      m_hFile = NULL;
   }

   m_bFirstReceive = true;

   return CBaseFilter::Stop();
}

int CSimpleWriter::GetPinCount()
{  
   if(m_pInput == NULL)
      return 0;

   return 1;
}

CBasePin *CSimpleWriter::GetPin(int n)
{  
   if(n == 0)
      return m_pInput;

   return NULL;
}

STDMETHODIMP CSimpleWriter::NonDelegatingQueryInterface(REFIID riid, void ** ppv)
{  

   CheckPointer(ppv, E_POINTER);
   CAutoLock lock(&m_Lock);

   if (riid == IID_IFileSinkFilter)
   {
      return GetInterface((IFileSinkFilter *)this, ppv);
   }
   else if (riid == IID_IMediaPosition || riid == IID_IMediaSeeking)
   {
      if (m_pPosition == NULL) 
      {
         HRESULT hr = S_OK;
         m_pPosition = new CPosPassThru(NAME("Writer Pass Through"), (IUnknown *) GetOwner(), (HRESULT *) &hr, m_pInput);

         if (m_pPosition == NULL) 
            return E_OUTOFMEMORY;

         if (FAILED(hr)) 
         {
            SAFE_DELETE(m_pPosition);
            return hr;
         }
      }

      return m_pPosition->NonDelegatingQueryInterface(riid, ppv);
   } 

   return OnQueryInterface(riid, ppv);
}

STDMETHODIMP CSimpleWriter::SetFileName(LPCOLESTR pszFileName, const AM_MEDIA_TYPE *pmt)
{  

   CheckPointer(pszFileName, E_POINTER);
   CheckPointer(m_pInput, E_POINTER);

   
   if(m_hFile != NULL)
   {
      ::CloseHandle(m_hFile);
      m_hFile = NULL;
   }

   
   m_hFile = ::CreateFile(pszFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, (DWORD)0, NULL);
   if(m_hFile == NULL || m_hFile == INVALID_HANDLE_VALUE)
      return E_FAIL;

   
   ::lstrcpy(m_awInputFileName, pszFileName);

   return S_OK;
}

STDMETHODIMP CSimpleWriter::GetCurFile(LPOLESTR *ppszFileName, AM_MEDIA_TYPE *pmt)
{  

   return E_NOTIMPL;
}

STDMETHODIMP CSimpleWriter::OnQueryInterface(REFIID riid, void ** ppv)
{
   return CBaseFilter::NonDelegatingQueryInterface(riid, ppv);
}

HRESULT CSimpleWriter::OnReceive(HANDLE hFile, IMediaSample *pInSample)
{  
   return NOERROR;
}

HRESULT CSimpleWriter::OnStart(HANDLE hFile)
{  
   return NOERROR;
}

HRESULT CSimpleWriter::OnStop(HANDLE hFile, bool bEos)
{  
   return NOERROR;
}

HRESULT CSimpleWriter::OnSeek(HANDLE hFile)
{  
   return NOERROR;
}

