/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

//
//  W A R N I N G
//  -------------
//
// This file is not part of the Qt API.  It exists for the convenience
// of other Qt classes.  This header file may change from version to
// version without notice, or even be removed.
//
// INTERNAL USE ONLY: Do NOT use for any other purpose.
//


#include <QtCore/qt_windows.h>
#include <QtCore/QDataStream>
#include <mmsystem.h>
#include "qwindowsaudiodeviceinfo.h"
#include "qwindowsaudioutils.h"

#if defined(Q_CC_MINGW) && !defined(__MINGW64_VERSION_MAJOR)
struct IBaseFilter; // Needed for strmif.h from stock MinGW.
struct _DDPIXELFORMAT;
typedef struct _DDPIXELFORMAT* LPDDPIXELFORMAT;
#endif

#include <strmif.h>
#if !defined(Q_CC_MINGW) || defined(__MINGW64_VERSION_MAJOR)
#  include <uuids.h>
#else

extern GUID CLSID_AudioInputDeviceCategory;
extern GUID CLSID_AudioRendererCategory;
extern GUID IID_ICreateDevEnum;
extern GUID CLSID_SystemDeviceEnum;

#ifndef __ICreateDevEnum_INTERFACE_DEFINED__
#define __ICreateDevEnum_INTERFACE_DEFINED__

DECLARE_INTERFACE_(ICreateDevEnum, IUnknown)
{
    STDMETHOD(CreateClassEnumerator)(REFCLSID clsidDeviceClass,
                                     IEnumMoniker **ppEnumMoniker,
                                     DWORD dwFlags) PURE;
};

#endif //  __ICreateDevEnum_INTERFACE_DEFINED__

#ifndef __IErrorLog_INTERFACE_DEFINED__
#define __IErrorLog_INTERFACE_DEFINED__

DECLARE_INTERFACE_(IErrorLog, IUnknown)
{
    STDMETHOD(AddError)(THIS_ LPCOLESTR, EXCEPINFO *) PURE;
};

#endif /* __IErrorLog_INTERFACE_DEFINED__ */

#ifndef __IPropertyBag_INTERFACE_DEFINED__
#define __IPropertyBag_INTERFACE_DEFINED__

const GUID IID_IPropertyBag = {0x55272A00, 0x42CB, 0x11CE, {0x81, 0x35, 0x00, 0xAA, 0x00, 0x4B, 0xB8, 0x51}};

DECLARE_INTERFACE_(IPropertyBag, IUnknown)
{
    STDMETHOD(Read)(THIS_ LPCOLESTR, VARIANT *, IErrorLog *) PURE;
    STDMETHOD(Write)(THIS_ LPCOLESTR, VARIANT *) PURE;
};

#endif /* __IPropertyBag_INTERFACE_DEFINED__ */

#endif // defined(Q_CC_MINGW) && !defined(__MINGW64_VERSION_MAJOR)

QT_BEGIN_NAMESPACE

// For mingw toolchain mmsystem.h only defines half the defines, so add if needed.
#ifndef WAVE_FORMAT_44M08
#define WAVE_FORMAT_44M08 0x00000100
#define WAVE_FORMAT_44S08 0x00000200
#define WAVE_FORMAT_44M16 0x00000400
#define WAVE_FORMAT_44S16 0x00000800
#define WAVE_FORMAT_48M08 0x00001000
#define WAVE_FORMAT_48S08 0x00002000
#define WAVE_FORMAT_48M16 0x00004000
#define WAVE_FORMAT_48S16 0x00008000
#define WAVE_FORMAT_96M08 0x00010000
#define WAVE_FORMAT_96S08 0x00020000
#define WAVE_FORMAT_96M16 0x00040000
#define WAVE_FORMAT_96S16 0x00080000
#endif


QWindowsAudioDeviceInfo::QWindowsAudioDeviceInfo(QByteArray dev, QAudio::Mode mode)
{
    QDataStream ds(&dev, QIODevice::ReadOnly);
    ds >> devId >> device;
    this->mode = mode;

    updateLists();
}

QWindowsAudioDeviceInfo::~QWindowsAudioDeviceInfo()
{
    close();
}

bool QWindowsAudioDeviceInfo::isFormatSupported(const QAudioFormat& format) const
{
    return testSettings(format);
}

QAudioFormat QWindowsAudioDeviceInfo::preferredFormat() const
{
    QAudioFormat nearest;
    if (mode == QAudio::AudioOutput) {
        nearest.setSampleRate(44100);
        nearest.setChannelCount(2);
        nearest.setByteOrder(QAudioFormat::LittleEndian);
        nearest.setSampleType(QAudioFormat::SignedInt);
        nearest.setSampleSize(16);
        nearest.setCodec(QLatin1String("audio/pcm"));
    } else {
        nearest.setSampleRate(11025);
        nearest.setChannelCount(1);
        nearest.setByteOrder(QAudioFormat::LittleEndian);
        nearest.setSampleType(QAudioFormat::SignedInt);
        nearest.setSampleSize(8);
        nearest.setCodec(QLatin1String("audio/pcm"));
    }
    return nearest;
}

QString QWindowsAudioDeviceInfo::deviceName() const
{
    return device;
}

QStringList QWindowsAudioDeviceInfo::supportedCodecs()
{
    return QStringList() << QStringLiteral("audio/pcm");
}

QList<int> QWindowsAudioDeviceInfo::supportedSampleRates()
{
    updateLists();
    return sampleRatez;
}

QList<int> QWindowsAudioDeviceInfo::supportedChannelCounts()
{
    updateLists();
    return channelz;
}

QList<int> QWindowsAudioDeviceInfo::supportedSampleSizes()
{
    updateLists();
    return sizez;
}

QList<QAudioFormat::Endian> QWindowsAudioDeviceInfo::supportedByteOrders()
{
    return QList<QAudioFormat::Endian>() << QAudioFormat::LittleEndian;
}

QList<QAudioFormat::SampleType> QWindowsAudioDeviceInfo::supportedSampleTypes()
{
    updateLists();
    return typez;
}


bool QWindowsAudioDeviceInfo::open()
{
    return true;
}

void QWindowsAudioDeviceInfo::close()
{
}

bool QWindowsAudioDeviceInfo::testSettings(const QAudioFormat& format) const
{
    WAVEFORMATEXTENSIBLE wfx;
    if (qt_convertFormat(format, &wfx)) {
        // query only, do not open device
        if (mode == QAudio::AudioOutput) {
            return (waveOutOpen(NULL, UINT_PTR(devId), &wfx.Format, 0, 0,
                                WAVE_FORMAT_QUERY) == MMSYSERR_NOERROR);
        } else { // AudioInput
            return (waveInOpen(NULL, UINT_PTR(devId), &wfx.Format, 0, 0,
                                WAVE_FORMAT_QUERY) == MMSYSERR_NOERROR);
        }
    }

    return false;
}

void QWindowsAudioDeviceInfo::updateLists()
{
    if (!sizez.isEmpty())
        return;

    DWORD fmt = 0;

    if(mode == QAudio::AudioOutput) {
        WAVEOUTCAPS woc;
        if (waveOutGetDevCaps(devId, &woc, sizeof(WAVEOUTCAPS)) == MMSYSERR_NOERROR)
            fmt = woc.dwFormats;
    } else {
        WAVEINCAPS woc;
        if (waveInGetDevCaps(devId, &woc, sizeof(WAVEINCAPS)) == MMSYSERR_NOERROR)
            fmt = woc.dwFormats;
    }

    sizez.clear();
    sampleRatez.clear();
    channelz.clear();
    typez.clear();

    if (fmt) {
        // Check sample size
        if ((fmt & WAVE_FORMAT_1M08)
            || (fmt & WAVE_FORMAT_1S08)
            || (fmt & WAVE_FORMAT_2M08)
            || (fmt & WAVE_FORMAT_2S08)
            || (fmt & WAVE_FORMAT_4M08)
            || (fmt & WAVE_FORMAT_4S08)
            || (fmt & WAVE_FORMAT_48M08)
            || (fmt & WAVE_FORMAT_48S08)
            || (fmt & WAVE_FORMAT_96M08)
            || (fmt & WAVE_FORMAT_96S08)) {
            sizez.append(8);
        }
        if ((fmt & WAVE_FORMAT_1M16)
            || (fmt & WAVE_FORMAT_1S16)
            || (fmt & WAVE_FORMAT_2M16)
            || (fmt & WAVE_FORMAT_2S16)
            || (fmt & WAVE_FORMAT_4M16)
            || (fmt & WAVE_FORMAT_4S16)
            || (fmt & WAVE_FORMAT_48M16)
            || (fmt & WAVE_FORMAT_48S16)
            || (fmt & WAVE_FORMAT_96M16)
            || (fmt & WAVE_FORMAT_96S16)) {
            sizez.append(16);
        }

        // Check sample rate
        if ((fmt & WAVE_FORMAT_1M08)
           || (fmt & WAVE_FORMAT_1S08)
           || (fmt & WAVE_FORMAT_1M16)
           || (fmt & WAVE_FORMAT_1S16)) {
            sampleRatez.append(11025);
        }
        if ((fmt & WAVE_FORMAT_2M08)
           || (fmt & WAVE_FORMAT_2S08)
           || (fmt & WAVE_FORMAT_2M16)
           || (fmt & WAVE_FORMAT_2S16)) {
            sampleRatez.append(22050);
        }
        if ((fmt & WAVE_FORMAT_4M08)
           || (fmt & WAVE_FORMAT_4S08)
           || (fmt & WAVE_FORMAT_4M16)
           || (fmt & WAVE_FORMAT_4S16)) {
            sampleRatez.append(44100);
        }
        if ((fmt & WAVE_FORMAT_48M08)
            || (fmt & WAVE_FORMAT_48S08)
            || (fmt & WAVE_FORMAT_48M16)
            || (fmt & WAVE_FORMAT_48S16)) {
            sampleRatez.append(48000);
        }
        if ((fmt & WAVE_FORMAT_96M08)
           || (fmt & WAVE_FORMAT_96S08)
           || (fmt & WAVE_FORMAT_96M16)
           || (fmt & WAVE_FORMAT_96S16)) {
            sampleRatez.append(96000);
        }

        // Check channel count
        if (fmt & WAVE_FORMAT_1M08
                || fmt & WAVE_FORMAT_1M16
                || fmt & WAVE_FORMAT_2M08
                || fmt & WAVE_FORMAT_2M16
                || fmt & WAVE_FORMAT_4M08
                || fmt & WAVE_FORMAT_4M16
                || fmt & WAVE_FORMAT_48M08
                || fmt & WAVE_FORMAT_48M16
                || fmt & WAVE_FORMAT_96M08
                || fmt & WAVE_FORMAT_96M16) {
            channelz.append(1);
        }
        if (fmt & WAVE_FORMAT_1S08
                || fmt & WAVE_FORMAT_1S16
                || fmt & WAVE_FORMAT_2S08
                || fmt & WAVE_FORMAT_2S16
                || fmt & WAVE_FORMAT_4S08
                || fmt & WAVE_FORMAT_4S16
                || fmt & WAVE_FORMAT_48S08
                || fmt & WAVE_FORMAT_48S16
                || fmt & WAVE_FORMAT_96S08
                || fmt & WAVE_FORMAT_96S16) {
            channelz.append(2);
        }

        typez.append(QAudioFormat::SignedInt);
        typez.append(QAudioFormat::UnSignedInt);

        // WAVEOUTCAPS and WAVEINCAPS contains information only for the previously tested parameters.
        // WaveOut and WaveInt might actually support more formats, the only way to know is to try
        // opening the device with it.
        QAudioFormat testFormat;
        testFormat.setCodec(QStringLiteral("audio/pcm"));
        testFormat.setByteOrder(QAudioFormat::LittleEndian);
        testFormat.setSampleType(QAudioFormat::SignedInt);
        testFormat.setChannelCount(channelz.first());
        testFormat.setSampleRate(sampleRatez.at(sampleRatez.size() / 2));
        testFormat.setSampleSize(sizez.last());
        const QAudioFormat defaultTestFormat(testFormat);

        // Check if float samples are supported
        testFormat.setSampleType(QAudioFormat::Float);
        testFormat.setSampleSize(32);
        if (testSettings(testFormat))
            typez.append(QAudioFormat::Float);

        // Check channel counts > 2
        testFormat = defaultTestFormat;
        for (int i = 3; i < 19; ++i) { // <mmreg.h> defines 18 different channels
            testFormat.setChannelCount(i);
            if (testSettings(testFormat))
                channelz.append(i);
        }

        // Check more sample sizes
        testFormat = defaultTestFormat;
        const QList<int> testSampleSizes = QList<int>() << 24 << 32 << 48 << 64;
        for (int s : testSampleSizes) {
            testFormat.setSampleSize(s);
            if (testSettings(testFormat))
                sizez.append(s);
        }

        // Check more sample rates
        testFormat = defaultTestFormat;
        const QList<int> testSampleRates = QList<int>() << 8000 << 16000 << 32000 << 88200 << 192000;
        for (int r : testSampleRates) {
            testFormat.setSampleRate(r);
            if (testSettings(testFormat))
                sampleRatez.append(r);
        }
        std::sort(sampleRatez.begin(), sampleRatez.end());
    }
}

QList<QByteArray> QWindowsAudioDeviceInfo::availableDevices(QAudio::Mode mode)
{
    Q_UNUSED(mode)

    QList<QByteArray> devices;
    //enumerate device fullnames through directshow api
    auto hrCoInit = CoInitialize(nullptr);
    ICreateDevEnum *pDevEnum = NULL;
    IEnumMoniker *pEnum = NULL;
    // Create the System device enumerator
    HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,
                 CLSCTX_INPROC_SERVER, IID_ICreateDevEnum,
                 reinterpret_cast<void **>(&pDevEnum));

    unsigned long iNumDevs = mode == QAudio::AudioOutput ? waveOutGetNumDevs() : waveInGetNumDevs();
    if (SUCCEEDED(hr)) {
        // Create the enumerator for the audio input/output category
        if (pDevEnum->CreateClassEnumerator(
             mode == QAudio::AudioOutput ? CLSID_AudioRendererCategory : CLSID_AudioInputDeviceCategory,
             &pEnum, 0) == S_OK) {
            pEnum->Reset();
            // go through and find all audio devices
            IMoniker *pMoniker = NULL;
            while (pEnum->Next(1, &pMoniker, NULL) == S_OK) {
                IPropertyBag *pPropBag;
                hr = pMoniker->BindToStorage(0,0,IID_IPropertyBag,
                     reinterpret_cast<void **>(&pPropBag));
                if (FAILED(hr)) {
                    pMoniker->Release();
                    continue; // skip this one
                }
                // Find if it is a wave device
                VARIANT var;
                VariantInit(&var);
                hr = pPropBag->Read(mode == QAudio::AudioOutput ? L"WaveOutID" : L"WaveInID", &var, 0);
                if (SUCCEEDED(hr)) {
                    LONG waveID = var.lVal;
                    if (waveID >= 0 && waveID < LONG(iNumDevs)) {
                        VariantClear(&var);
                        // Find the description
                        hr = pPropBag->Read(L"FriendlyName", &var, 0);
                        if (SUCCEEDED(hr)) {
                            QByteArray  device;
                            QDataStream ds(&device, QIODevice::WriteOnly);
                            ds << quint32(waveID) << QString::fromWCharArray(var.bstrVal);
                            devices.append(device);
                        }
                    }
                }

                pPropBag->Release();
                pMoniker->Release();
            }
            pEnum->Release();
        }
        pDevEnum->Release();
    }
    if (SUCCEEDED(hrCoInit))
        CoUninitialize();

    return devices;
}

QByteArray QWindowsAudioDeviceInfo::defaultDevice(QAudio::Mode mode)
{
    const QString &name = (mode == QAudio::AudioOutput) ? QStringLiteral("Default Output Device")
                                                        : QStringLiteral("Default Input Device");
    QByteArray defaultDevice;
    QDataStream ds(&defaultDevice, QIODevice::WriteOnly);
    ds << quint32(WAVE_MAPPER) // device ID for default device
       << name;

    return defaultDevice;
}

QT_END_NAMESPACE
