www.pudn.com > WMACompressor.zip > yeti.WmaWriter.h


// 
//  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY 
//  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 
//  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR 
//  PURPOSE. IT CAN BE DISTRIBUTED FREE OF CHARGE AS LONG AS THIS HEADER  
//  REMAINS UNCHANGED. 
// 
//  Email:  yetiicb@hotmail.com 
// 
//  Copyright (C) 2002-2004 Idael Cardoso.  
// 
#pragma once 
 
#include "WmaWriterConfig.h" 
#include "WriterSink.h" 
#include "WmaWriter.h" 
 
using namespace System; 
using namespace System::IO; 
using namespace System::Runtime::InteropServices; 
using namespace WaveLib; 
using namespace Yeti::MMedia; 
 
 
namespace Yeti 
{ 
  namespace MMedia 
  { 
    namespace Wmf 
    { 
      public __gc class WmaWriter : public AudioWriter, public IWriterSink 
	      { 
        protected: 
          CWmaWriter* m_Writer; 
          bool m_HeaderWrote; 
          int m_HeaderSize; 
          __int64 m_HeaderPos; 
           
          void Init(WmaWriterProfile* Profile) 
          { 
            m_Writer = NULL; 
            m_HeaderWrote = false; 
            CProfile* pPrf = Profile->pProfile; 
            if (pPrf != NULL) 
            { 
              try 
              { 
                CComPtr Sink; 
                CWriterSink::Create( dynamic_cast(this), &Sink); 
                try 
                { 
                  GCHandle h = GCHandle::Alloc(m_InputDataFormat, GCHandleType::Pinned); 
                  try 
                  { 
                    WAVEFORMATEX* pf = (WAVEFORMATEX*)h.AddrOfPinnedObject().ToPointer(); 
                    m_Writer = new CWmaWriter(pf, pPrf->m_Profile, Sink); 
                  } 
                  __finally 
                  { 
                    h.Free(); 
                  } 
                } 
                __finally 
                { 
                  Sink = NULL; 
                } 
              } 
              __finally 
              { 
                delete pPrf; 
              } 
            } 
            else 
            { 
              throw new ArgumentException("Invalid profile", "Profile"); 
            } 
          } 
        public: 
 
          WmaWriter(System::IO::Stream*  Output, WaveLib::WaveFormat __gc* Format, WmaWriterProfile __gc* Profile) 
            :AudioWriter(Output, Format) 
          { 
          Init(Profile); 
          } 
          WmaWriter(System::IO::Stream*  Output, WmaWriterConfig* Config) 
            :AudioWriter(Output, Config) 
          { 
            Init(Config->Profile); 
          } 
          WmaWriter(System::IO::Stream*  Output, WaveLib::WaveFormat* Format) 
            :AudioWriter(Output, Format) 
          { 
            Init(WmaWriterProfileManager::AudioSystemProfiles[0]); 
          } 
        public: //IWriterSink 
          HRESULT OnHeader(/* [in] */INSSBuffer *pHeader) 
          { 
            try 
            { 
              DWORD Length = 0; 
              Byte buffer[] = NULL; 
              CComPtr pManRef; 
              if ( SUCCEEDED(pHeader->QueryInterface(__uuidof(IManBufferRef), (void**)&pManRef)) ) 
              { 
                void* IntfHandle = NULL; 
                pManRef->GetManBuffer(&IntfHandle); 
                GCHandle h = GCHandle::op_Explicit(IntPtr(IntfHandle)); 
			          IManBuffer* ManBuff = static_cast(h.Target); 
                Length = ManBuff->UsedLength; 
                buffer = ManBuff->Buffer; 
              } 
              else 
              { 
                BYTE* pBuffer = NULL; 
                if ( SUCCEEDED(pHeader->GetBufferAndLength(&pBuffer, &Length)) ) 
                { 
                  buffer = new Byte[Length]; 
                  Marshal::Copy(IntPtr(pBuffer), buffer, 0, Length); 
                } 
              } 
              if ( !m_HeaderWrote ) 
              { 
                if (BaseStream->CanSeek) 
                { 
                  m_HeaderPos = BaseStream->Position; 
                } 
                __super::Write(buffer, 0, Length); 
                m_HeaderSize = Length; 
                m_HeaderWrote = true; 
              } 
              else 
                if ( (m_HeaderSize == Length) && (BaseStream->CanSeek) ) 
                { 
                  __int64 pos = BaseStream->Position; 
                  BaseStream->Position = m_HeaderPos; 
                  __super::Write(buffer, 0, Length); 
                  BaseStream->Position = pos; 
                } 
            } 
            catch(...) 
            { 
            } 
            return S_OK; 
          } 
          HRESULT AllocateDataUnit(/* [in] */DWORD cbDataUnit,/* [out] */ INSSBuffer **ppDataUnit) 
          { 
            IManBuffer* ManBuff = new ManBuffer(cbDataUnit); 
            CBuffer::Create(ManBuff, ppDataUnit); 
            return S_OK; 
          } 
          HRESULT IsRealTime(/* [out] */ BOOL *pfRealTime) 
          { 
            *pfRealTime = false; 
            return S_OK; 
          } 
          HRESULT OnDataUnit(/* [in] */INSSBuffer *pDataUnit) 
          { 
          try 
            { 
              CComPtr pManRef; 
              if ( SUCCEEDED(pDataUnit->QueryInterface(__uuidof(IManBufferRef), (void**)&pManRef)) ) 
              { 
                void* IntfHandle = NULL; 
                pManRef->GetManBuffer(&IntfHandle); 
                GCHandle h = GCHandle::op_Explicit(IntPtr(IntfHandle)); 
			          IManBuffer* ManBuffer = static_cast(h.Target); 
                __super::Write(ManBuffer->Buffer, 0, ManBuffer->UsedLength); 
              } 
              else 
              { 
                DWORD size = 0; 
                BYTE* pBuffer = NULL; 
                if ( SUCCEEDED(pDataUnit->GetBufferAndLength(&pBuffer, &size)) ) 
                { 
                  Byte Buffer[] = new Byte[size]; 
                  Marshal::Copy(IntPtr(pBuffer), Buffer, 0, size); 
                  __super::Write(Buffer, 0, size); 
                } 
              } 
            } 
            catch(...) 
            { 
            } 
            return S_OK; 
          } 
          HRESULT OnEndWriting( void) 
          { 
            return S_OK; 
          } 
        protected: 
          virtual int GetOptimalBufferSize() 
          { 
            return m_InputDataFormat->nAvgBytesPerSec /10; 
          } 
          virtual String* GetDefaultAudioFileExtension() 
          { 
            return S"wma"; 
          } 
        public: //overrides 
          virtual void Close() 
          { 
            if (m_Writer != NULL) 
            { 
              delete m_Writer; 
              m_Writer = NULL; 
            } 
            __super::Close(); 
          } 
          virtual void Write(Byte Buffer[], int index, int count) 
          { 
            if ( (count % m_InputDataFormat->nBlockAlign) == 0 ) 
            { 
              if ( (index+count) > Buffer->Length ) 
              { 
                throw new IndexOutOfRangeException(); 
              } 
              Byte __pin* pBuffer = &Buffer[index]; 
              m_Writer->Write(pBuffer, count); 
            } 
            else 
            { 
              throw new ArgumentException(String::Format(S"Invalid buffer size. Buffer size must be aligned to {0} bytes.", __box(m_InputDataFormat->nBlockAlign)), String::Format(S"count={0}", __box(count))); 
            } 
          } 
          virtual void Write(Byte Buffer[]) 
          { 
            Write(Buffer, 0, Buffer->Length); 
          } 
        }; 
    } 
  } 
}