/*
 * Implementation of IAudioData Interface
 *
 * Copyright 2012 Christian Costa
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#include "wine/debug.h"

#define COBJMACROS

#include "winbase.h"
#include "amstream_private.h"

#include "amstream.h"

WINE_DEFAULT_DEBUG_CHANNEL(amstream);

typedef struct {
    IAudioData IAudioData_iface;
    LONG ref;
} AMAudioDataImpl;

static inline AMAudioDataImpl *impl_from_IAudioData(IAudioData *iface)
{
    return CONTAINING_RECORD(iface, AMAudioDataImpl, IAudioData_iface);
}

/*** IUnknown methods ***/
static HRESULT WINAPI IAudioDataImpl_QueryInterface(IAudioData *iface, REFIID riid, void **ret_iface)
{
    TRACE("(%p)->(%s,%p)\n", iface, debugstr_guid(riid), ret_iface);

    if (IsEqualGUID(riid, &IID_IUnknown) ||
        IsEqualGUID(riid, &IID_IMemoryData) ||
        IsEqualGUID(riid, &IID_IAudioData))
    {
        IUnknown_AddRef(iface);
        *ret_iface = iface;
        return S_OK;
    }

    ERR("(%p)->(%s,%p),not found\n", iface, debugstr_guid(riid), ret_iface);
    return E_NOINTERFACE;
}

static ULONG WINAPI IAudioDataImpl_AddRef(IAudioData* iface)
{
    AMAudioDataImpl *This = impl_from_IAudioData(iface);
    ULONG ref = InterlockedIncrement(&This->ref);

    TRACE("(%p)->(): new ref = %u\n", iface, This->ref);

    return ref;
}

static ULONG WINAPI IAudioDataImpl_Release(IAudioData* iface)
{
    AMAudioDataImpl *This = impl_from_IAudioData(iface);
    ULONG ref = InterlockedDecrement(&This->ref);

    TRACE("(%p)->(): new ref = %u\n", iface, This->ref);

    if (!ref)
        HeapFree(GetProcessHeap(), 0, This);

    return ref;
}

/*** IMemoryData methods ***/
static HRESULT WINAPI IAudioDataImpl_SetBuffer(IAudioData* iface, DWORD size, BYTE *data, DWORD flags)
{
    FIXME("(%p)->(%u,%p,%x): stub\n", iface, size, data, flags);

    return E_NOTIMPL;
}

static HRESULT WINAPI IAudioDataImpl_GetInfo(IAudioData* iface, DWORD *length, BYTE **data, DWORD *actual_data)
{
    FIXME("(%p)->(%p,%p,%p): stub\n", iface, length, data, actual_data);

    return E_NOTIMPL;
}

static HRESULT WINAPI IAudioDataImpl_SetActual(IAudioData* iface, DWORD data_valid)
{
    FIXME("(%p)->(%u): stub\n", iface, data_valid);

    return E_NOTIMPL;
}

/*** IAudioData methods ***/
static HRESULT WINAPI IAudioDataImpl_GetFormat(IAudioData* iface, WAVEFORMATEX *wave_format_current)
{
    FIXME("(%p)->(%p): stub\n", iface, wave_format_current);

    return E_NOTIMPL;
}

static HRESULT WINAPI IAudioDataImpl_SetFormat(IAudioData* iface, const WAVEFORMATEX *wave_format)
{
    FIXME("(%p)->(%p): stub\n", iface, wave_format);

    return E_NOTIMPL;
}

static const struct IAudioDataVtbl AudioData_Vtbl =
{
    /*** IUnknown methods ***/
    IAudioDataImpl_QueryInterface,
    IAudioDataImpl_AddRef,
    IAudioDataImpl_Release,
    /*** IMemoryData methods ***/
    IAudioDataImpl_SetBuffer,
    IAudioDataImpl_GetInfo,
    IAudioDataImpl_SetActual,
    /*** IAudioData methods ***/
    IAudioDataImpl_GetFormat,
    IAudioDataImpl_SetFormat
};

HRESULT AMAudioData_create(IUnknown *pUnkOuter, LPVOID *ppObj)
{
    AMAudioDataImpl *object;

    TRACE("(%p,%p)\n", pUnkOuter, ppObj);

    if (pUnkOuter)
        return CLASS_E_NOAGGREGATION;

    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(AMAudioDataImpl));
    if (!object)
    {
        ERR("Out of memory\n");
        return E_OUTOFMEMORY;
    }

    object->IAudioData_iface.lpVtbl = &AudioData_Vtbl;
    object->ref = 1;

    *ppObj = &object->IAudioData_iface;

    return S_OK;
}
