/* ***** BEGIN LICENSE BLOCK *****
 * Source last modified: $Id: aud_strm_hlpr.cpp,v 1.1.4.1 2004/11/24 18:07:05 acolwell Exp $
 * 
 * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
 * 
 * The contents of this file, and the files included with this file,
 * are subject to the current version of the RealNetworks Public
 * Source License (the "RPSL") available at
 * http://www.helixcommunity.org/content/rpsl unless you have licensed
 * the file under the current version of the RealNetworks Community
 * Source License (the "RCSL") available at
 * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
 * will apply. You may also obtain the license terms directly from
 * RealNetworks.  You may not use this file except in compliance with
 * the RPSL or, if you have a valid RCSL with RealNetworks applicable
 * to this file, the RCSL.  Please see the applicable RPSL or RCSL for
 * the rights, obligations and limitations governing use of the
 * contents of the file.
 * 
 * Alternatively, the contents of this file may be used under the
 * terms of the GNU General Public License Version 2 or later (the
 * "GPL") in which case the provisions of the GPL are applicable
 * instead of those above. If you wish to allow use of your version of
 * this file only under the terms of the GPL, and not to allow others
 * to use your version of this file under the terms of either the RPSL
 * or RCSL, indicate your decision by deleting the provisions above
 * and replace them with the notice and other provisions required by
 * the GPL. If you do not delete the provisions above, a recipient may
 * use your version of this file under the terms of any one of the
 * RPSL, the RCSL or the GPL.
 * 
 * This file is part of the Helix DNA Technology. RealNetworks is the
 * developer of the Original Code and owns the copyrights in the
 * portions it created.
 * 
 * This file, and the files included with this file, is distributed
 * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
 * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
 * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
 * ENJOYMENT OR NON-INFRINGEMENT.
 * 
 * Technology Compatibility Kit Test Suite(s) Location:
 *    http://www.helixcommunity.org/content/tck
 * 
 * Contributor(s):
 * 
 * ***** END LICENSE BLOCK ***** */
#include "aud_strm_hlpr.h"

#include "hxassert.h"

#include "debug.h" // DPRINTF()
#define D_AUD_HLPR 0 //0x2000000

COggAudioStreamHelper::COggAudioStreamHelper() :
    m_lRefCount(0),
    m_pAudioStream(NULL),
    m_pODN(NULL)
{
#ifdef _DEBUG
    debug_level() |= D_AUD_HLPR;
#endif /* _DEBUG */

    DPRINTF(D_AUD_HLPR, ("COASH::COASH %p\n", this));
}

COggAudioStreamHelper::~COggAudioStreamHelper()
{
    DPRINTF(D_AUD_HLPR, ("COASH::~COASH %p\n", this));
    Close();
}

HX_RESULT 
COggAudioStreamHelper::Init(IHXAudioStream* pAudioStream)
{
    DPRINTF(D_AUD_HLPR, ("COASH::Init %p\n", this));

    HX_RESULT res = HXR_INVALID_PARAMETER;
    
    if (pAudioStream)
    {
        HX_ASSERT(!m_pAudioStream);

        if (!m_pAudioStream)
        {
            m_pAudioStream = pAudioStream;
            m_pAudioStream->AddRef();
            res = m_pAudioStream->AddDryNotification(this);
        }
        else
        {
            res = HXR_UNEXPECTED;
        }
    }

    return res;
}
    
HX_RESULT 
COggAudioStreamHelper::GetStreamInfo(REF(UINT32) uSampleRate, 
                                     REF(UINT32) uChannels)
{
    HX_RESULT res = HXR_UNEXPECTED;

    if (m_pAudioStream)
    {
        IHXAudioStream2* pAS2 = NULL;
        
        res = m_pAudioStream->QueryInterface(IID_IHXAudioStream2,
                                             (void**)&pAS2);

        if (HXR_OK == res)
        {
            HXAudioFormat fmt;

            res = pAS2->GetAudioFormat(&fmt);

            if (HXR_OK == res)
            {
                DPRINTF(D_AUD_HLPR, ("COASH::GSI %p : %u %u\n", 
                                     this, fmt.ulSamplesPerSec,
                                     fmt.uChannels));

                uSampleRate = fmt.ulSamplesPerSec;
                uChannels = fmt.uChannels;
            }
        }
    }

    return res;
}

HX_RESULT 
COggAudioStreamHelper::SetDryNotification(IHXDryNotification* pODN)
{
    DPRINTF(D_AUD_HLPR, ("COASH::SDN %p : %p\n", this, pODN));

    HX_RELEASE(m_pODN);

    if (pODN)
    {
        m_pODN = pODN;
        m_pODN->AddRef();
    }
    
    return HXR_OK;
}

HX_RESULT 
COggAudioStreamHelper::Write(HXAudioData* pAudioData)
{
    HX_RESULT res = HXR_INVALID_PARAMETER;

    if (pAudioData)
    {
        if (m_pAudioStream)
        {
            res = m_pAudioStream->Write(pAudioData);
        }
        else
        {
            res = HXR_UNEXPECTED;
        }
    }

    return res;
}

void COggAudioStreamHelper::Close()
{
    if (m_pAudioStream)
    {
        IHXAudioStream2* pStream2 = NULL;
        
        if (HXR_OK == m_pAudioStream->QueryInterface(IID_IHXAudioStream2, 
                                                     (void**)&pStream2))
        {
            /* Remove our OnDryNotification for this stream */
            pStream2->RemoveDryNotification(this);
        }
        HX_RELEASE(pStream2);
        HX_RELEASE(m_pAudioStream);
    }
    HX_RELEASE(m_pODN);
}

/*
 *  IUnknown methods
 */
STDMETHODIMP
COggAudioStreamHelper::QueryInterface(THIS_
                                      REFIID riid,
                                      void** ppvObj)
{
    if (IsEqualIID(riid, IID_IUnknown)) {
        AddRef();
        *ppvObj = (IUnknown *)(IHXDryNotification *)this;
        return HXR_OK;
    } 
    else if (IsEqualIID(riid, IID_IHXDryNotification)) {
        AddRef();
        *ppvObj = (IHXDryNotification *)this;
        return HXR_OK;
    } 

    *ppvObj = NULL;
    return HXR_NOINTERFACE;
}

STDMETHODIMP_(ULONG32)
COggAudioStreamHelper::AddRef(THIS)
{
    return InterlockedIncrement(&m_lRefCount);
}

STDMETHODIMP_(ULONG32)
COggAudioStreamHelper::Release(THIS)
{
    if (InterlockedDecrement(&m_lRefCount) > 0)
        return m_lRefCount;

    delete this;
    return 0;
}

/*
 *  IHXDryNotification methods
 */

STDMETHODIMP
COggAudioStreamHelper::OnDryNotification(THIS_
                                         UINT32 ulCurrentStreamTime,
                                         UINT32 ulMinimumDurationRequired)
{
    DPRINTF(D_AUD_HLPR, ("COASH::ODN %p : %u %u\n", 
                         this,
                         ulCurrentStreamTime,
                         ulMinimumDurationRequired));
    
    HX_RESULT res = HXR_OK;

    if (m_pODN)
    {
        res = m_pODN->OnDryNotification(ulCurrentStreamTime,
                                        ulMinimumDurationRequired);
    }

    return res;
}
