#ifndef RT_Audio_C_H_
#define RT_Audio_C_H_

#include "common_c.h"

typedef rtc::MicrophoneStatus AVDMicrophoneStatus;
/**
* 房间中音频模块回调接口.
*
* 音频模块回调接口定义了房间中音频相关如麦克风、扬声器的通知和异步操作返回。
*/
typedef struct Audio_Callback {
	/// 通知
	/** 麦克风状态更改通知
	*
	* @param[in] audioHandle 音频模块句柄。
	* @param[in] status 麦克风状态。
	* @param[in] *userId 设备关联用户Id。
	* @note 当麦克风状态更改后，房间内所有用户接收到此通知。
	* @sa avd_audio_openMicrophone
	* @sa avd_audio_closeMicrophone
	*/
	void(*audio_onMicrophoneStatusNotify)(AVDHandle audioHandle, AVDMicrophoneStatus status, const char* userId);

	void(*audio_onAudioLevelMonitorNotify)(AVDHandle audioHandle, const AVDAudioInfo& info);
	
	/// 异步返回
	/** 本用户打开麦克风异步返回
	*
	* @param[in] audioHandle 音频模块句柄。
	* @param[in] result 错误代码。
	* @sa avd_audio_openMicrophone
	*/
	void(*audio_onOpenMicrophoneResult) (AVDHandle audioHandle, Result result);
	/** 本用户关闭麦克风异步返回
	*
	* @param[in] audioHandle 音频模块句柄。
	* @param[in] result 错误代码。
	* @sa avd_audio_closeMicrophone
	*/
	void(*audio_onCloseMicrophoneResult)(AVDHandle audioHandle, Result result);

	/// 异步返回
	/** 本用户订阅音频异步返回
	*
	* @param[in] result 错误代码。
	* @param[in] fromId 用户Id，唯一标示一个用户。
	*
	* @sa subscribe
	*/
	void(*audio_onSubscribeResult)(AVDHandle audioHandle, Result result, const char* userId);
	/** 本用户取消订阅音频异步返回
	*
	* @param[in] result 错误代码。
	* @param[in] fromId 用户Id，唯一标示一个用户。
	*
	* @sa unsubscribe
	*/
	void(*audio_onUnsubscribeResult)(AVDHandle audioHandle, Result result, const char* userId);

	Audio_Callback() {
		audio_onMicrophoneStatusNotify = NULL;
		audio_onOpenMicrophoneResult = NULL;
		audio_onCloseMicrophoneResult = NULL;
		audio_onSubscribeResult = NULL;
		audio_onUnsubscribeResult = NULL;
		audio_onAudioLevelMonitorNotify = NULL;
	}
}*LPAudio_Callback;
///

/**
* 房间中音频模块接口.
*
* 房间音频模块定义房间音频相关如麦克风、扬声器相关操作功能接口。
*/
extern "C" {
	/** 初始化音频模块接口.
	*
	* @param[in] roomHandle 房间句柄。
	* @param[in] cb 音频模块回调接口指针。
	* @param[out] audioHandle 音频模块句柄。
	* @return 返回错误代码。
	* @sa Audio_Callback
	*/
	RT_API_EXPORT Result avd_audio_init(AVDHandle roomHandle, LPAudio_Callback cb, AVDHandle& audioHandle);
	/** 反初始化音频模块接口.
	*
	* @param[in] audioHandle 音频模块句柄。
	* @return 返回错误代码。
	*/
	RT_API_EXPORT Result avd_audio_uninit(AVDHandle audioHandle);
	/** 打开本地麦克风发布到房间中
	*
	* @param[in] audioHandle 音频模块句柄。
	* @return 返回错误代码。
	* @note 为异步操作，操作结果在 audio_onOpenMicrophoneResult 中返回。
	* @sa audio_onOpenMicrophoneResult
	*/
	RT_API_EXPORT Result avd_audio_openMicrophone(AVDHandle audioHandle);
	/** 关闭本地麦克风发布到房间中
	*
	* @param[in] audioHandle 音频模块句柄。
	* @return 返回错误代码。
	* @note 为异步操作，操作结果在 audio_onCloseMicrophoneResult 中返回。
	* @sa audio_onCloseMicrophoneResult
	*/
	RT_API_EXPORT Result avd_audio_closeMicrophone(AVDHandle audioHandle);
	/** 获取本地麦克风状态
	* @param[in] audioHandle 音频模块句柄。
	* @return 返回麦克风状态。
	*/
	RT_API_EXPORT AVDMicrophoneStatus avd_audio_getMicrophoneStatus(AVDHandle audioHandle);
	/** 本地麦克风静默
	*
	* @param[in] audioHandle 音频模块句柄。
	* @return 返回错误代码。
	* @note 麦克风静默表示本地没有声音传递到房间中，房间中用户不会听到本地的任何声音。
	*/
	RT_API_EXPORT Result avd_audio_muteMicrophone(AVDHandle audioHandle);
	/** 本地麦克风取消静默
	*
	* @param[in] audioHandle 音频模块句柄。
	* @return 返回错误代码。
	*/
	RT_API_EXPORT Result avd_audio_unmuteMicrophone(AVDHandle audioHandle);
	/** 判断本地麦克风是否静默
	* @param[in] audioHandle 音频模块句柄。
	* @return 麦克风是否被静默。
	*/
	RT_API_EXPORT AVDBool avd_audio_ismuteMicrophone(AVDHandle audioHandle);
	/** 本地扬声器静默
	*
	* @param[in] audioHandle 音频模块句柄。
	* @return 返回错误代码。
	* @note 扬声器静默表示房间中的声音不会在本地扬声器播放，本用户不会听到任何房间中的声音。
	*/
	RT_API_EXPORT Result avd_audio_muteSpeaker(AVDHandle audioHandle);
	/** 本地扬声器取消静默
	* @param[in] audioHandle 音频模块句柄。
	* @return 返回错误代码。
	*/
	RT_API_EXPORT Result avd_audio_unmuteSpeaker(AVDHandle audioHandle);
	/** 判断本地扬声器是否静默
	* @param[in] audioHandle 音频模块句柄。
	* @return 扬声器是否被静默。
	*/
	RT_API_EXPORT AVDBool avd_audio_ismuteSpeaker(AVDHandle audioHandle);
	/** 获取远端麦克风状态
	* @param[in] audioHandle 音频模块句柄。
	* @param[in] *userId 关联用户Id。
	* @return 返回麦克风状态。
	*/
	RT_API_EXPORT AVDMicrophoneStatus avd_audio_getRemoteMicrophoneStatus(AVDHandle audioHandle, const char* userId);
	/** 命令远端用户打开麦克风
	* @param[in] audioHandle 音频模块句柄。
	* @param[in] *userId 关联用户Id。
	* @return 返回错误代码。
	*/
	RT_API_EXPORT Result avd_audio_remotecmdOpenMicrophone(AVDHandle audioHandle, const char* userId);
	/** 命令远端用户关闭麦克风
	* @param[in] audioHandle 音频模块句柄。
	* @param[in] *userId 关联用户Id。
	* @return 返回错误代码。
	*/
	RT_API_EXPORT Result avd_audio_remotecmdCloseMicrophone(AVDHandle audioHandle, const char* userId);
	/** 开启语音激励功能
	* @return 返回错误代码。
	*/
	RT_API_EXPORT Result avd_audio_monitorAudioLevel(AVDHandle audioHandle);
	/** 关闭语音激励
	* @return 返回错误代码。
	*/
	RT_API_EXPORT Result avd_audio_unmonitorAudioLevel(AVDHandle audioHandle);
	/** 判断是否开启语音激励
	*/
	RT_API_EXPORT AVDBool avd_audio_ismonitorAudioLevel(AVDHandle audioHandle);

	/** 当前AVD引擎使用音频导入作为音频源
	* @return 返回错误代码：
	* 	AVD_OK						成功
	* @note 当前音频导入为全局唯一的单个对象，启用导入后，所有房间的音频都使用此导入的数据。
	*/
	RT_API_EXPORT Result avd_audio_enableImportAudioData(AVDBool isEnable);
	/** 给Capturer输入PCM原始数据
	*
	* @param[in] timestamp_ns 时间戳, nanos second。
	* @param[in] sampleRate 音频采样率
	* @param[in] channels 音频采集通道数
	* @param[in] data 音频内容数据指针
	* @param[in] len  音频内容大小
	* @return 返回错误代码：
	* 	AVD_OK						成功
	* @note sampleRate和channels可以变化(但是不能频繁变化，如每次都不一样，内部每次变化的时候需要重新处理缓冲区)，每次输入的音频采样数据不能太多，最大不超过4K。
	*
	*/
	RT_API_EXPORT Result avd_audio_importCapturedFrame(
		uint64 timestamp_ns, int sampleRate, int channels, const uint8* data, size_t len);
	/** 给Capturer输入AAC编码后的数据
	*
	* @param[in] timestamp_ns 时间戳, nanos second。
	* @param[in] sampleRate 音频采样率
	* @param[in] channels 音频采集通道数
	* @param[in] data 音频内容数据指针
	* @param[in] len  音频内容大小
	* @param[in] samplesOfEncodedData  音频编码数据包含的采样数（一般情况AAC每次编码都是1024 * channels个采样）
	* @return 返回错误代码：
	* 	AVD_OK						成功
	*
	*/
	RT_API_EXPORT Result avd_audio_importAACFrame(
		uint64 timestamp_ns, int sampleRate, int channels, const uint8* data, size_t len, int samplesOfEncodedData);
	/* */
	/** 订阅一个用户的音频
	*
	* @param[in] userId 用户Id。
	* @return 返回错误代码。
	* @note 订阅操作为异步操作，操作结果在 onSubscribeResult 中返回。房间中发布的音频缺省已经订阅，所以一般不需要调用
	* 此函数，只有调用了unsubscribe后，若又需要此音频时才调用此函数。
	* @sa onSubscribeResult
	*/
	RT_API_EXPORT Result avd_audio_subscribe(AVDHandle audioHandle, const char* userId);
	/** 取消订阅一个用户的音频
	*
	* @param[in] userId 用户Id。
	* @return 返回错误代码。
	* @note 取消订阅操作为异步操作，操作结果在 onUnsubscribeResult 中返回。房间中发布的音频缺省已经订阅，如果不想听某
	* 用户的声音，可以调用此函数来取消订阅。
	* @sa onUnsubscribeResult
	*/
	RT_API_EXPORT Result avd_audio_unsubscribe(AVDHandle audioHandle, const char* userId);


	/** 获取已经publish的音频用户数
	*
	* @return 返回发布用户数量。
	*/
	RT_API_EXPORT uint32 avd_audio_getPubAudioUsersCount(AVDHandle audioHandle);

	/** 获取已经sub的音频用户数量
	*
	@return 返回订阅用户数量。
	*/
	RT_API_EXPORT uint32 avd_audio_getSubAudioUsersCount(AVDHandle audioHandle);
	/** 根据索引获取发布的摄像头信息
	*
	* @param[in] audioHandle 视频模块句柄。
	* @param[in] index 索引编号，从0开始。
	* @param[out] item 用户id。
	* @return 返回错误代码。
	*/
	RT_API_EXPORT Result avd_audio_getPubAudioUserByIndex(AVDHandle audioHandle, uint32 index, AVDUserId& item);

	/** 根据索引获取订阅的摄像头信息
	*
	* @param[in] audioHandle 视频模块句柄。
	* @param[in] index 索引编号，从0开始。
	* @param[out] item 用户id。
	* @return 返回错误代码。
	*/
	RT_API_EXPORT Result avd_audio_getSubdAudioUserByIndex(AVDHandle audioHandle, uint32 index, AVDUserId& item);

	/** 获取已经publish的音频用户
	*
	* @param[in,out] ncounts 用户列表数。
	* @param[in,out] items 用户列表。
	* @return 返回错误代码。
	*/
	RT_API_EXPORT Result avd_audio_getPubAudioUsers(AVDHandle audioHandle, uint32& ncounts, AVDUserId*&  items);
	/** 获取已经Subscrib的音频用户
	*
	* @param[in,out] ncounts 用户列表数。
	* @param[in,out] items 用户列表。
	* @return 返回错误代码。
	*/
	RT_API_EXPORT Result avd_audio_getSubAudioUsers(AVDHandle audioHandle, uint32& ncounts, AVDUserId*&  items);
	/** 判断用户音频是否已经发布
	* @param[in] userId 摄像头Id，唯一标示用户ID。
	* @return 返回是否是已发布的用户。
	*/
	RT_API_EXPORT AVDBool avd_audio_isAudioPublished(AVDHandle audioHandle, const char* userId);
	/** 判断用户音频是否已经订阅
	* @param[in] userId 摄像头Id，唯一标示用户ID。
	* @return 返回是否是已订阅的用户。
	*/
	RT_API_EXPORT AVDBool avd_audio_isAudioSubscribed(AVDHandle audioHandle, const char* userId);
}
///
typedef AVDDevice AVDMicrophone;
typedef AVDDevice AVDSpeaker;
/**
* 房间中音频模块回调接口.
*
* 音频模块回调接口定义了房间中音频相关如麦克风、扬声器的通知和异步操作返回。
*/
typedef struct AudioDevice_Callback {
	/// 通知
	/** 麦克风插入通知
	*
	* @param[in] adeviceHandle 音频设备管理模块句柄。
	* @param[in] item 麦克风信息。
	* @note 当系统中有麦克风设备插入时，此回调触发。
	*/
	void(*audiodevice_onMicrophonePlugin)(AVDHandle adeviceHandle, AVDMicrophone& item);
	/** 麦克风拔出通知
	*
	* @param[in] adeviceHandle 音频设备管理模块句柄。
	* @param[in] item 麦克风信息。
	* @note 当系统中有麦克风设备拔出时，此回调触发。
	*/
	void(*audiodevice_onMicrophonePlugout)(AVDHandle adeviceHandle, AVDMicrophone& item);
	/** 扬声器插入通知
	*
	* @param[in] adeviceHandle 音频设备管理模块句柄。
	* @param[in] item 扬声器信息。
	* @note 当系统中有扬声器设备插入时，此回调触发。
	*/
	void(*audiodevice_onSpeakerPlugin)(AVDHandle adeviceHandle, AVDSpeaker& item);
	/** 扬声器拔出通知
	*
	* @param[in] adeviceHandle 音频设备管理模块句柄。
	* @param[in] item 扬声器信息。
	* @note 当系统中有扬声器设备拔出时，此回调触发。
	*/
	void(*audiodevice_onSpeakerPlugout)(AVDHandle adeviceHandle, AVDSpeaker& item);
	//
	/** 麦克风音量变化通知
	*
	* @param[in] adeviceHandle 音频设备管理模块句柄。
	* @param[in] volume 麦克风音量，取值：0 至 100，0为最小，100最大。
	* @note 当系统中有麦克风音量变化时，此回调触发。
	*/
	void(*audiodevice_onMicrophoneVolumeChanged) (AVDHandle adeviceHandle, uint32 volume);
	/** 扬声器音量变化通知
	*
	* @param[in] adeviceHandle 音频设备管理模块句柄。
	* @param[in] volume 扬声器音量，取值：0 至 100，0为最小，100最大。
	* @note 当系统中有扬声器音量变化时，此回调触发。
	*/
	void(*audiodevice_onSpeakerVolumeChanged)(AVDHandle adeviceHandle, uint32 volume);
	AudioDevice_Callback() {
		audiodevice_onMicrophonePlugin = NULL;
		audiodevice_onMicrophonePlugout = NULL;
		audiodevice_onSpeakerPlugin = NULL;
		audiodevice_onSpeakerPlugout = NULL;
		audiodevice_onMicrophoneVolumeChanged = NULL;
		audiodevice_onSpeakerVolumeChanged = NULL;
	}
}*LPAudioDevice_Callback;

///
extern "C" {
	/**
	* 音频设备管理接口.
	*
	* 音频设备管理接口定义房间中音频设备相关功能接口。
	*/

	/** 初始化音频设备管理接口
	*
	* @param[in] audioHandle 音频模块句柄。
	* @param[in] cb 音频设备管理回调接口指针。
	* @param[out] adeviceHandle 音频设备管理模块句柄。
	* @return 返回错误代码。
	* @sa AudioDevice_Callback
	*/
	RT_API_EXPORT Result avd_audiodevice_init(AVDHandle audioHandle, LPAudioDevice_Callback cb, AVDHandle& adeviceHandle);
	/** 反初始化音频设备管理接口
	*
	* @param[in] adeviceHandle 音频设备模块句柄。
	* @return 返回错误代码。
	*/
	RT_API_EXPORT Result avd_audiodevice_uninit(AVDHandle adeviceHandle);
	/** 获取本机麦克风设备数量
	*
	* @param[in] adeviceHandle 音频设备模块句柄。
	* @return 麦克风数量。
	*/
	RT_API_EXPORT uint32 avd_audiodevice_getMicrophoneCount(AVDHandle adeviceHandle);
	/** 根据索引获取本机麦克风设备信息
	*
	* @param[in] adeviceHandle 音频设备模块句柄。
	* @param[in] index 索引编号，从0开始。
	* @param[out] item 麦克风信息。
	* @return 返回错误代码。
	*/
	RT_API_EXPORT Result avd_audiodevice_getMicrophone(AVDHandle adeviceHandle, uint32 index, AVDMicrophone& item);
	/** 获取本机麦克风设备信息列表
	*
	* @param[in] adeviceHandle 音频设备模块句柄。
	* @param[in,out] ncount 传入列表容量，传出获取到的麦克风数量。
	* @param[out] *&mics 麦克风设备集合存放列表。
	* @return 返回错误代码。
	*/
	RT_API_EXPORT Result avd_audiodevice_getMicrophones(AVDHandle adeviceHandle, uint32& ncount, AVDMicrophone*& mics);
	/** 获取本机扬声器声音输出设备数量
	*
	* @param[in] adeviceHandle 音频设备模块句柄。
	* @return 扬声器数量。
	*/
	RT_API_EXPORT uint32 avd_audiodevice_getSpeakerCount(AVDHandle adeviceHandle);
	/** 根据索引获取本机扬声器声音输出设备信息
	*
	* @param[in] adeviceHandle 音频设备模块句柄。
	* @param[in] index 索引编号，从0开始。
	* @param[out] item 扬声器信息。
	* @return 返回错误代码。
	*/
	RT_API_EXPORT Result avd_audiodevice_getSpeaker(AVDHandle adeviceHandle, uint32 index, AVDSpeaker& item);
	/** 获取本机扬声器设备信息列表
	*
	* @param[in] adeviceHandle 音频设备模块句柄。
	* @param[in,out] ncount 传入列表容量，传出获取到的麦克风数量。
	* @param[out] *&spks 扬声器设备集合存放列表。
	* @return 返回错误代码。
	*/
	RT_API_EXPORT Result avd_audiodevice_getSpeakers(AVDHandle adeviceHandle, uint32& ncount, AVDSpeaker*& spks);
	/** 获取当前默认使用的本机麦克风设备信息
	*
	* @param[in] adeviceHandle 音频设备模块句柄。
	* @param[out] item 麦克风设备信息。
	* @return 返回错误代码。
	*/
	RT_API_EXPORT Result avd_audiodevice_getRecordingMicrophone(AVDHandle adeviceHandle, AVDMicrophone& item);
	/** 设置当前默认使用的本机麦克风设备信息
	*
	* @param[in] adeviceHandle 音频设备模块句柄。
	* @param[out] *deviceId 录音麦克风ID号。
	* @return 返回错误代码。
	*/
	RT_API_EXPORT Result avd_audiodevice_setRecordingMicrophone(AVDHandle adeviceHandle, const char* deviceId);
	/** 获取当前默认使用的本机扬声器设备信息
	*
	* @param[in] adeviceHandle 音频设备模块句柄。
	* @param[out] item 扬声器设备信息。
	* @return 返回错误代码。
	*/
	RT_API_EXPORT Result avd_audiodevice_getPlayoutSpeaker(AVDHandle adeviceHandle, AVDSpeaker& item);
	/** 设置当前默认使用的本机扬声器设备信息
	*
	* @param[in] adeviceHandle 音频设备模块句柄。
	* @param[out] *deviceId 扬声器ID号。
	* @return 返回错误代码。
	*/
	RT_API_EXPORT Result avd_audiodevice_setPlayoutSpeaker(AVDHandle adeviceHandle, const char* deviceId);
	/** 获取麦克风录音音量
	*
	* @param[in] adeviceHandle 音频设备模块句柄。
	* @return 麦克风录音音量，取值：0 至 100，0为最小，100最大。
	*/
	RT_API_EXPORT uint32 avd_audiodevice_getRecordingVolume(AVDHandle adeviceHandle);
	/** 获取扬声器播放音量
	*
	* @param[in] adeviceHandle 音频设备模块句柄。
	* @return 扬声器播放音量，取值：0 至 100，0为最小，100最大。。
	*/
	RT_API_EXPORT uint32 avd_audiodevice_getPlayoutVolume(AVDHandle adeviceHandle);
	/** 设置录音的音量大小
	*
	* @param[in] adeviceHandle 音频设备模块句柄。
	* @param[in] volume 麦克风音量，取值：0 至 100，0为最小，100最大。
	* @return 返回错误代码。
	*/
	RT_API_EXPORT Result avd_audiodevice_setRecordingVolume(AVDHandle adeviceHandle, uint32 volume);
	/** 设置扬声器播放音量大小
	*
	* @param[in] adeviceHandle 音频设备模块句柄。
	* @param[in] volume 扬声器音量，取值：0 至 100，0为最小，100最大。
	* @return 返回错误代码。
	*/
	RT_API_EXPORT Result avd_audiodevice_setPlayoutVolume(AVDHandle adeviceHandle, uint32 volume);

	///for testing
	/** 开始录制并且播放声音
	*
	* @param[in] adeviceHandle 音频设备模块句柄。
	* @return 返回错误代码。
	* @note 用于测试麦克风和扬声器是否工作正常。
	*/
	RT_API_EXPORT Result avd_audiodevice_recordPlayStart(AVDHandle adeviceHandle);
	/** 停止录制并且停止播放声音
	*
	* @param[in] adeviceHandle 音频设备模块句柄。
	* @return 返回错误代码。
	*/
	RT_API_EXPORT Result avd_audiodevice_recordPlayStop(AVDHandle adeviceHandle);
	/** 开始播放声音文件
	*
	* @param[in] adeviceHandle 音频设备模块句柄。
	* @param[in] *file 音频文件。
	* @param[in] loop 单次播放结束后，是否重复播放。
	* @param[in] format 指定音频文件格式。
	* @return 返回错误代码。
	* @note 用于测试扬声器是否工作正常。
	*/
	RT_API_EXPORT Result avd_audiodevice_playVoice(AVDHandle adeviceHandle, const char* file, AVDBool loop, rtc::FileFormats format);
	/** 停止播放声音文件
	*
	* @param[in] adeviceHandle 音频设备模块句柄。
	* @return 返回错误代码。
	*/
	RT_API_EXPORT Result avd_audiodevice_stopVoice(AVDHandle adeviceHandle);

	/** 是否正在播放声音文件
	*
	* @return true,false。
	*/
	RT_API_EXPORT AVDBool avd_audiodevice_isPlayingVoice(AVDHandle adeviceHandle);
	/** 获取录音能级0-9
	*
	* @return 能级大小。
	*/
	RT_API_EXPORT uint32 avd_audiodevice_getRecordLevel(AVDHandle adeviceHandle);
	/** 获取播放声音能级0-9
	*
	* @return 能级大小。
	*/
	RT_API_EXPORT uint32 avd_audiodevice_getPlayoutLevel(AVDHandle adeviceHandle);

	/** 获取虚拟录音设备ID
	*
	* @return 获取虚拟录音设备ID。
	*/
	RT_API_EXPORT Result avd_audiodevice_getFakeMicrophoneId(AVDHandle adeviceHandle, char* deviceId, uint32& didsize);
}

#endif//RT_Audio_C_H_
