////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//   Wireless Communication Library 7                                         //
//                                                                            //
//   Copyright (C) 2006-2024 Mike Petrichenko                                 //
//                           Soft Service Company                             //
//                           All Rights Reserved                              //
//                                                                            //
//   http://www.btframework.com                                               //
//                                                                            //
//   support@btframework.com                                                  //
//   shop@btframework.com                                                     //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////

#pragma once

#include <vector>
#include <set>

#include <tchar.h>

#include "..\Common\wclHelpers.h"
#include "..\Common\wclMessaging.h"

#include "wclAudioErrors.h"

/// <summary> This macro helps to build correct documentation. </summary>
#define _WCL_AUDIO_API_INCLUDE_FILE_ "wclAudioApi.h"
#include _WCL_AUDIO_API_INCLUDE_FILE_

namespace wclAudio
{

/// <summary> The audio device data flow direction. </summary>
/// <remarks> The Data Flow indicates the direction in which audio data flows
///   between an audio endpoint device and an application. </remarks>
typedef enum
{
	/// <summary> Audio rendering stream. Audio data flows from the application
	///   to the audio endpoint device, which renders the stream. </summary>
	dfRender,
	/// <summary> Audio capture stream. Audio data flows from the audio endpoint
	///   device that captures the stream, to the application. </summary>
	dfCapture
} wclAudioDeviceDataFlow;

/// <summary> The audio device role. </summary>
/// <remarks> indicate the role that the system has assigned to an audio
///   endpoint device. </remarks>
typedef enum
{
	/// <summary> Games, system notification sounds, and voice
	///   commands. </summary>
	drConsole,
	/// <summary> Music, movies, narration, and live music
	///   recording. </summary>
	drMultimedia,
	/// <summary> Voice communications (talking to another person). </summary>
	drCommunications
} wclAudioDeviceRole;
/// <summary> The device roles set. </summary>
/// <seealso cref="wclAudioDeviceRole" />
typedef std::set<wclAudioDeviceRole> wclAudioDeviceRoles;

/// <summary> Audio device state. </summary>
typedef enum
{
	/// <summary> Active device. </summary>
	asActive,
	/// <summary> Disabled device. </summary>
	asDisabled,
	/// <summary> Not present device. </summary>
	asNotPresent,
	/// <summary> Unplugged device. </summary>
	asUnplugged
} wclAudioDeviceState;
/// <summary> Set of audio device states. </summary>
/// <seealso cref="wclAudioDeviceState" />
typedef std::set<wclAudioDeviceState> wclAudioDeviceStates;

/// <summary> The audio peak values array. </summary>
typedef std::vector<float> wclAudioPeakValues;

/// <summary> The hardware support features for an audio endpoint
///   device. </summary>
typedef enum
{
	/// <summary> The audio endpoint device supports a hardware volume
	///   control. </summary>
	hfVolume,
	/// <summary> The audio endpoint device supports a hardware mute
	///   control. </summary>
	hfMute,
	/// <summary> The audio endpoint device supports a hardware peak
	///   meter. </summary>
	hfMeter
} wclAudioHardwareFeature;
/// <summary> The hardware support flags for an audio endpoint
///   device. </summary>
/// <seealso cref="wclAudioHardwareFeature" />
typedef std::set<wclAudioHardwareFeature> wclAudioHardwareFeatures;

/// <summary> Contains information about audio device. </summary>
typedef struct
{
	/// <summary> Device's ID. </summary>
	tstring Id;
	/// <summary> Device friendly name. </summary>
	tstring FriendlyName;
	/// <summary> Device description. </summary>
	tstring Description;
	/// <summary> The data flow. </summary>
	/// <seealso cref="wclAudioDeviceDataFlow" />
    wclAudioDeviceDataFlow Flow;
	/// <summary> The device default roles. </summary>
	/// <seealso cref="wclAudioDeviceRoles" />
    wclAudioDeviceRoles Roles;
	/// <summary> The device state. </summary>
	/// <seealso cref="wclAudioDeviceState" />
    wclAudioDeviceState State;
	/// <summary> <c>True</c> if the audio device is connected by
	///   Bluetooth. </summary>
	bool IsBluetooth;
	/// <summary> The device's MAC address if device is Bluetooth. Valid only if
    ///   <c>IsBluetooth</c> is <c>True</c>.</summary>
	__int64 Mac;
	/// <summary> Bluetooth service UUID. Valid only if <c>IsBluetooth</c> is
    ///   <c>True</c>. </summary>
	GUID Service;
} wclAudioDevice;
/// <summary> The array of audio devices. </summary>
/// <seealso cref="wclAudioDevice" />
typedef std::vector<wclAudioDevice> wclAudioDevices;

/// <summary> The Audio Switcher <c>OnDefaultDeviceChanged</c> event handler
///   prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="Id"> The device ID. </param>
/// <param name="Flow"> The device data flow. </param>
/// <param name="Role"> The device role. </param>
/// <seealso cref="wclAudioDeviceDataFlow" />
/// <seealso cref="wclAudioDeviceRole" />
#define wclAudioDefaultDeviceChangedEvent(_event_name_) \
	__event void _event_name_(void* Sender, const tstring& Id, \
	const wclAudioDeviceDataFlow Flow, const wclAudioDeviceRole Role)
/// <summary> The Audio Switcher <c>OnDeviceAdded</c> and
///   <c>OnDeviceRemoved</c> events handler prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="Id"> The device ID. </param>
#define wclAudioDeviceEvent(_event_name_) \
	__event void _event_name_(void* Sender, const tstring& Id);
/// <summary> The Audio Switcher <c>OnStateChanged</c> event handler
///   prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="Id"> The device ID. </param>
/// <param name="State"> The new device state. </param>
/// <seealso cref="wclAudioDeviceState" />
#define wclAudioDeviceStateChangedEvent(_event_name_) \
	__event void _event_name_(void* Sender, const tstring& Id, \
	const wclAudioDeviceState State);
/// <summary> The Audio Volume <c>OnChanged</c> event handler
///   prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="Muted"> The mute state. </param>
/// <param name="Volume"> The master volume. </param>
/// <param name="Volumes"> The channel volumes. </param>
#define wclAudioVolumeChangedEvent(_event_name_) \
	__event void _event_name_(void* Sender, const bool Muted, \
	const float Volume, const wclAudioPeakValues& Volumes);

/// <summary> The custom Audio component. </summary>
/// <remarks> The class implements the basic Audio features for all Audio
///   component. </remarks>
class CwclCustomAudio
{
	DISABLE_COPY(CwclCustomAudio);

private:
	IMMDeviceEnumerator*	FEnumerator;
	IMMNotificationClient*	FEventHandler;
	CwclMessageReceiver*	FReceiver;

protected:
	/// <summary> The method called during audio subsystem
	///   finalization. </summary>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to provide extra
	///   finalization code. </remarks>
	virtual int InternalClose();
	/// <summary> The method called during audio subsystem
	///   initialization. </summary>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to provide extra
	///   initialization code. </remarks>
	virtual int InternalOpen();

	/// <summary> The method called when a new notification message
	///   received. </summary>
	/// <param name="Message"> A <see cref="CwclMessage" /> object
	///   represents a notification message. </param>
	/// <remarks> <para> This method is for internal use only. </para>
	///   <para> If a derived class overrides this method it must always call
	///   the inherited implementation first. </para> </remarks>
	/// <seealso cref="CwclMessage" />
	virtual void MessageReceived(const CwclMessage* const Message);
	
	/// <summary> Calls the <c>OnClosed</c> event. </summary>
	virtual void DoClosed();
	/// <summary> Calls the <c>OnOpend</c> event. </summary>
	virtual void DoOpened();

	/// <summary> Opens the Audio component. </summary>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	virtual int Open();
	
	/// <summary> Gets the Audio devices enumerator interface. </summary>
	/// <returns> The Audio device enumerator interface. </returns>
	IMMDeviceEnumerator* GetEnumerator() const;
	/// <summary> Gets the Audio devices enumerator interface. </summary>
	/// <value> The Audio device enumerator interface. </value>
	__declspec(property(get = GetEnumerator)) IMMDeviceEnumerator* Enumerator;
	
	/// <summary> Gets the message receiver. </summary>
	/// <returns> The message receiver object. </returns>
	/// <seealso cref="CwclMessageReceiver" />
	CwclMessageReceiver* GetReceiver() const;
	/// <summary> Gets the message receiver. </summary>
	/// <value> The message receiver object. </value>
	/// <seealso cref="CwclMessageReceiver" />
    __declspec(property(get = GetReceiver)) CwclMessageReceiver* Receiver;

public:
	/// <summary> Creates new Audio component. </summary>
	CwclCustomAudio();
	/// <summary> Frees the component. </summary>
	virtual ~CwclCustomAudio();
	
	/// <summary> Closes the Audio component. </summary>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	virtual int Close();
	
	/// <summary> Gets the Audio Switcher state. </summary>
	/// <returns> <c>True</c> if the Audio Switcher is active. <c>False</c>
	///   otherwsie. </returns>
	bool GetActive() const;
	/// <summary> Gets the Audio Switcher state. </summary>
	/// <value> <c>True</c> if the Audio Switcher is active. <c>False</c>
	///   otherwsie. </value>
	__declspec(property(get = GetActive)) bool Active;

	/// <summary> The event fires when the Audio Switcher was closed. </summary>
	/// <param name="Sender"> The object that initiated the event. </param>
	wclNotifyEvent(OnClosed);
    /// <summary> The event fires when the Audio Switcher was opened. </summary>
    /// <param name="Sender"> The object that initiated the event. </param>
	wclNotifyEvent(OnOpened);
};

/// <summary> The base component for Audio components that works with a single
///  Audio endpoint. </summary>
/// <seealso cref="CwclCustomAudio" />
class CwclCustomAudioEndpoint : public CwclCustomAudio
{
	DISABLE_COPY(CwclCustomAudioEndpoint);
	
private:
	tstring	FId;
	
protected:
	/// <summary> The method called when a new notification message
	///   received. </summary>
	/// <param name="Message"> A <see cref="CwclMessage" /> object
	///   represents a notification message. </param>
	/// <remarks> <para> This method is for internal use only. </para>
	///   <para> If a derived class overrides this method it must always call
	///   the inherited implementation first. </para> </remarks>
	/// <seealso cref="CwclMessage" />
	virtual void MessageReceived(const CwclMessage* const Message) override;
	
	/// <summary> Fires the OnDisconnected event. </summary>
	virtual void DoDisconnected();
	
public:
	/// <summary> Creates new custom audio endpoint component. </summary>
	CwclCustomAudioEndpoint();
	
	/// <summary> Closes the audio endpoint. </summary>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	int Close() override;
	/// <summary> Opens the specified audio endpoint. </summary>
	/// <param name="Id"> The endpoint ID. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	virtual int Open(const tstring& Id);

	/// <summary> Gets the number of channels in the audio stream that are
	///   monitored by peak meters. </summary>
	/// <param name="Count"> The variable into which the method writes the
	///   number of channels. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to provide
	///   specific implementation. </remarks>
	virtual int GetChannels(unsigned long& Count) = 0;
	/// <summary> Queries the audio endpoint device for its hardware-supported
	///   functions. </summary>
	/// <param name="Features"> The variable into which the method writes a
	///   hardware support features that indicates the hardware capabilities of
	///   the audio endpoint device. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to provide
	///   specific implementation. </remarks>
	/// <seealso cref="wclAudioHardwareFeatures" />
	virtual int GetHardwareFeatures(wclAudioHardwareFeatures& Features) = 0;

	/// <summary> Gets the endpoint ID. </summary>
	/// <returns> The endpoint ID string. </returns>
	tstring GetId() const;
	/// <summary> Gets the endpoint ID. </summary>
	/// <value> The endpoint ID string. </value>
	__declspec(property(get = GetId)) tstring Id;
	
	/// <summary> The even fires when the endpoint used by this class has been
    ///   disconnected or removed. </summary>
	/// <param name="Sender"> The object that initiated the event. </param>
	wclNotifyEvent(OnDisconnected);
};

/// <summary> The class provides functional to select system default audio
///   device. </summary>
/// <seealso cref="CwclCustomAudio" />
class CwclAudioSwitcher : public CwclCustomAudio
{
	DISABLE_COPY(CwclAudioSwitcher);
	
private:
	void GetBluetoothDetails(wclAudioDevice& Device);

	bool GetDeviceProps(IMMDevice* const MMDevice, wclAudioDevice& Device);
    wclAudioDeviceRoles GetRoles(const EDataFlow Flow, const tstring& Id);
	
	int EnumDevices(const wclAudioDeviceStates& States, wclAudioDevices& Devices);

	int CheckDeviceState(const tstring& Id, const bool Connect);
	bool IsBtStr(LPWSTR str);
	int ChangeDeviceState(const tstring& Id, const bool Connect);

protected:
	/// <summary> The method called when a new notification message
    ///   received. </summary>
    /// <param name="Message"> A <see cref="CwclMessage" /> object
    ///   represents a notification message. </param>
    /// <remarks> <para> This method is for internal use only. </para>
    ///   <para> If a derived class overrides this method it must always call
    ///   the inherited implementation first. </para> </remarks>
    /// <seealso cref="CwclMessage" />
    virtual void MessageReceived(const CwclMessage* const Message) override;

	/// <summary> Calls the <c>OnDefaultDeviceChanged</c> event. </summary>
    /// <param name="Id"> The device ID. </param>
    /// <param name="Flow"> The device data flow. </param>
    /// <param name="Role"> The device role. </param>
    /// <seealso cref="wclAudioDeviceDataFlow" />
    /// <seealso cref="wclAudioDeviceRole" />
    virtual void DoDefaultDeviceChanged(const tstring& Id, const wclAudioDeviceDataFlow Flow,
		const wclAudioDeviceRole Role);
	/// <summary> Calls the <c>OnDeviceAdded</c> event. </summary>
	/// <param name="Id"> The device ID. </param>
	virtual void DoDeviceAdded(const tstring& Id);
	/// <summary> Calls the <c>OnDeviceRemoved</c> event. </summary>
	/// <param name="Id"> The device ID. </param>
	virtual void DoDeviceRemoved(const tstring& Id);
	/// <summary> Calls the <c>OnStateChanged</c> event. </summary>
	/// <param name="Id"> The device ID. </param>
	/// <param name="State"> The new device state. </param>
	/// <seealso cref="wclAudioDeviceState" />
	virtual void DoStateChanged(const tstring& Id, const wclAudioDeviceState State);

public:
    /// <summary> Creates new Audio Switcher component. </summary>
	CwclAudioSwitcher();

	/// <summary> Opens the Audio Switcher component. </summary>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    virtual int Open() override;
	
	/// <summary> Enumerates available audio devices. </summary>
	/// <param name="States"> The audio device states. </param>
	/// <param name="Devices"> If the method completed with success on output
	///   contains the list of found audio devices. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <seealso cref="wclAudioDeviceStates" />
	/// <seealso cref="wclAudioDevices" />
	int Enum(const wclAudioDeviceStates& States, wclAudioDevices& Devices);

	/// <summary> Gets the specified Audio Device information. </summary>
	/// <param name="Id"> The Audio Device ID. </param>
	/// <param name="Device"> If the method completed with success on output
	///   contains information about specified Audio Device. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <seealso cref="wclAudioDevice" />
	int GetDeviceDetails(const tstring& Id, wclAudioDevice& Device);

	/// <summary> Gets the default Audio Device for the specified Role and
    ///   Data Flow. </summary>
	/// <param name="Role"> The device role. </param>
	/// <param name="Flow"> The audio data flow. </param>
	/// <param name="Id"> If the method completed with success on output
	///   contains the default Audio Device ID. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <seealso cref="wclAudioDeviceRole" />
	/// <seealso cref="wclAudioDeviceDataFlow" />
    int GetDefault(const wclAudioDeviceRole Role, const wclAudioDeviceDataFlow Flow,
		tstring& Id);
	/// <summary> Sets the specified Audio Device as default for the specified
	///   Role. </summary>
	/// <param name="Role"> The device role. </param>
	/// <param name="Id"> The device ID. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <seealso cref="wclAudioDeviceRole" />
	int SetDefault(const wclAudioDeviceRole Role, const tstring& Id);
	
	/// <summary> Connects to the specified Audio Device. </summary>
	/// <param name="Id"> The device ID. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	int Connect(const tstring& Id);
	/// <summary> Connects to the specified Audio Device. </summary>
	/// <param name="Address"> The device Bluetooth MAC address. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	int Connect(const __int64 Address);

	/// <summary> Disconnects from the specified Audio Device. </summary>
	/// <param name="Id"> The device ID. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	int Disconnect(const tstring& Id);
	/// <summary> Disconnects from the specified Audio Device. </summary>
	/// <param name="Address"> The device Bluetooth MAC address. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	int Disconnect(const __int64 Address);

    /// <summary> The event fires when default audio device changed. </summary>
    /// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Id"> The device ID. </param>
	/// <param name="Flow"> The device data flow. </param>
	/// <param name="Role"> The device role. </param>
	/// <seealso cref="wclAudioDeviceDataFlow" />
	/// <seealso cref="wclAudioDeviceRole" />
	wclAudioDefaultDeviceChangedEvent(OnDefaultDeviceChanged);
    /// <summary> The event fires when new audio device added. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Id"> The device ID. </param>
	wclAudioDeviceEvent(OnDeviceAdded);
	/// <summary> The event fires when audio device removed. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Id"> The device ID. </param>
	wclAudioDeviceEvent(OnDeviceRemoved);
    /// <summary> The event fires when audio device state changed. </summary>
    /// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Id"> The device ID. </param>
	/// <param name="State"> The new device state. </param>
	/// <seealso cref="wclAudioDeviceState" />
    wclAudioDeviceStateChangedEvent(OnStateChanged);
};

/// <summary> The Audio Meter component represents a peak meter on an audio
///   stream to or from an audio endpoint device. </summary>
/// <seealso cref="CwclCustomAudioEndpoint"/>
class CwclAudioMeter : public CwclCustomAudioEndpoint
{
	DISABLE_COPY(CwclAudioMeter);
	
private:
	IAudioMeterInformation*	FMeter;
	
protected:
	/// <summary> The method called during audio subsystem
	///   finalization. </summary>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	virtual int InternalClose() override;
	/// <summary> The method called during audio subsystem
	///   initialization. </summary>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	virtual int InternalOpen() override;
	
public:
	/// <summary> Creates new audio meter component. </summary>
	CwclAudioMeter();
	
	/// <summary> Gets the number of channels in the audio stream that are
	///   monitored by peak meters. </summary>
	/// <param name="Count"> The variable into which the method writes the
	///   number of channels. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	virtual int GetChannels(unsigned long& Count) override;
	/// <summary> Gets the peak sample value for the channels in the audio
	///   stream. </summary>
	/// <param name="Values"> The variable into which the method writes the peak
	///   sample value for the audio stream. The peak value is a number in the
	///   normalized range from 0.0 to 1.0. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <seealso cref="wclAudioPeakValues" />
	int GetChannelsPeak(wclAudioPeakValues& Values);
	/// <summary> Queries the audio endpoint device for its hardware-supported
	///   functions. </summary>
	/// <param name="Features"> The variable into which the method writes a
	///   hardware support features that indicates the hardware capabilities of
	///   the audio endpoint device. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <seealso cref="wclAudioHardwareFeatures" />
	virtual int GetHardwareFeatures(wclAudioHardwareFeatures& Features) override;
	/// <summary> Gets the peak sample value in the audio stream. </summary>
	/// <param name="Value"> The variable into which the method writes the peak
	///   sample value for the audio stream. The peak value is a number in the
	///   normalized range from 0.0 to 1.0. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	int GetPeak(float& Value);
};

/// <summary> The component provides methods to control volume control for
///   an audio endpoints. </summary>
/// <seealso cref="CwclCustomAudioEndpoint" />
class CwclAudioVolume : public CwclCustomAudioEndpoint
{
	DISABLE_COPY(CwclAudioVolume);
	
private:
	GUID							FContext;
	IAudioEndpointVolume*			FVolume;
	IAudioEndpointVolumeCallback*	FVolumeCallback;
	
protected:
	/// <summary> The method called when a new notification message
	///   received. </summary>
	/// <param name="Message"> A <see cref="CwclMessage" /> object
	///   represents a notification message. </param>
	/// <remarks> <para> This method is for internal use only. </para>
	///   <para> If a derived class overrides this method it must always call
	///   the inherited implementation first. </para> </remarks>
	/// <seealso cref="CwclMessage" />
	virtual void MessageReceived(const CwclMessage* const Message) override;
	
	/// <summary> The method called during audio subsystem
	///   finalization. </summary>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	virtual int InternalClose() override;
	/// <summary> The method called during audio subsystem
	///   initialization. </summary>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	virtual int InternalOpen() override;
	
	/// <summary> The method fires the <c>OnChanged</c> event. </summary>
	/// <param name="Muted"> The mute state. </param>
	/// <param name="Volume"> The master volume. </param>
	/// <param name="Volumes"> The channel volumes. </param>
	virtual void DoChanged(const bool Muted, const float Volume,
		const wclAudioPeakValues& Volumes);
	
public:
	/// <summary> Creates new audio volume component. </summary>
	CwclAudioVolume();
	
	/// <summary> Gets the number of channels in the audio stream that are
	///   controlled by the volume control. </summary>
	/// <param name="Count"> The variable into which the method writes the
	///   number of channels. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	virtual int GetChannels(unsigned long& Count) override;
	/// <summary> Queries the audio endpoint device for its hardware-supported
	///   functions. </summary>
	/// <param name="Features"> The variable into which the method writes a
	///   hardware support features that indicates the hardware capabilities of
	///   the audio endpoint device. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <seealso cref="wclAudioHardwareFeatures" />
	virtual int GetHardwareFeatures(wclAudioHardwareFeatures& Features) override;
	
	/// <summary> Gets the channel volume level of the audio stream that enters
	///   or leaves the audio endpoint device. The volume level is expressed as
	///   a normalized, audio-tapered value in the range from 0.0
	///   to 1.0. </summary>
	/// <param name="Channel"> The audio endpoint channel number. The value
	///   must be in range between 0 and <c>Channels - 1</c>. </param>
	/// <param name="Volume"> The variable into which the method writes the
	///   volume level. The level is expressed as a normalized value in the
	///   range from 0.0 to 1.0. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	int GetChannelVolume(const unsigned long Channel, float& Volume);
	/// <summary> Gets the audio endpoint mute. </summary>
	/// <param name="Mute"> If the method completed with success on output
	///   contains the mute state of the audio endpoint. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	int GetMute(bool& Mute);
	/// <summary> Gets the master volume level of the audio stream that enters
	///   or leaves the audio endpoint device. The volume level is expressed as
	///   a normalized, audio-tapered value in the range from 0.0
	///   to 1.0. </summary>
	/// <param name="Volume"> The variable into which the method writes the
	///   volume level. The level is expressed as a normalized value in the
	///   range from 0.0 to 1.0. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	int GetVolume(float& Volume);
	
	/// <summary> Sets the channel volume level of the audio stream that enters
	///   or leaves the audio endpoint device. The volume level is expressed as
	///   a normalized, audio-tapered value in the range from 0.0
	///   to 1.0. </summary>
	/// <param name="Channel"> The audio endpoint channel number. The value
	///   must be in range between 0 and <c>Channels - 1</c>. </param>
	/// <param name="Value"> The volume level. The level is expressed as a
	///   normalized value in the range from 0.0 to 1.0. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	int SetChannelVolume(const unsigned long Channel, const float Value);
	/// <summary> Sets the audio endpoint mute. </summary>
	/// <param name="Mute"> The mute state of the audio endpoint. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	int SetMute(const bool Mute);
	/// <summary> Sets the master volume level of the audio stream that enters
	///   or leaves the audio endpoint device. The volume level is expressed as
	///   a normalized, audio-tapered value in the range from 0.0
	///   to 1.0. </summary>
	/// <param name="Value"> The volume level. The level is expressed as a
	///   normalized value in the range from 0.0 to 1.0. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	int SetVolume(const float Value);

	/// <summary> The event fires when the volumes of the specified audio
    ///   endpoint changed. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Muted"> The mute state. </param>
	/// <param name="Volume"> The master volume. </param>
	/// <param name="Volumes"> The channel volumes. </param>
	wclAudioVolumeChangedEvent(OnChanged);
};

}