/**
{file:
	{name: VidyoVirtualRenderer.h}
	{description: Virtual renderer API. }
	{copyright:
		(c) 2013-2021 Vidyo, Inc.,
		433 Hackensack Avenue,
		Hackensack, NJ  07601.
		All rights reserved.
		The information contained herein is proprietary to Vidyo, Inc.
		and shall not be reproduced, copied (in whole or in part), adapted,
		modified, disseminated, transmitted, transcribed, stored in a retrieval
		system, or translated into any language in any form by any means
		without the express written consent of Vidyo, Inc.}
}
*/

#ifndef VIDYO_VIRTUAL_RENDERER_H
#define VIDYO_VIRTUAL_RENDERER_H

#include <Lmi/Os/LmiSharedPtr.h>
#include <Lmi/Utils/LmiMap.h>
#include <Lmi/Utils/LmiStringVector.h>
#include <Lmi/Utils/LmiUnordered.h>
#include <Lmi/Utils/LmiVector.h>

LMI_BEGIN_EXTERN_C

#pragma mark - VidyoVirtualRenderer types declaration
struct VidyoVirtualRendererImpl_;
typedef struct VidyoVirtualRendererImpl_ VidyoVirtualRendererImpl;
Declare_LmiSharedPtr(VidyoVirtualRendererImpl)
Declare_LmiSharedPtrWrapper(VidyoVirtualRenderer, VidyoVirtualRendererImpl)
Declare_LmiWeakPtrWrapper(VidyoVirtualRendererHandle, VidyoVirtualRenderer, VidyoVirtualRendererImpl)

#define VIDYO_VIRTUALRENDERER_INVALIDTOKEN 0

/**
{type  apigroup="connector,simple" reference-counted="yes":
	{name: VidyoVirtualRenderer}
	{parent: Device}
	{include: Lmi/VidyoClient/VidyoVirtualRenderer.h}
	{description: This object represents a virtual renderer on the local endpoint.}
	{member:
		{name: id}
		{type: LmiString}
		{description: Unique ID.}
	}
	{member:
		{name: name}
		{type: LmiString}
		{description: Name of the virtual renderer.}
	}
}
*/

/**
{type visibility="private":
	{name: VidyoVirtualRendererHandle}
	{parent: VidyoVirtualRenderer}
	{description: Weak reference to VidyoVirtualRenderer object.}
}
*/

#pragma mark - Include child objects
LMI_END_EXTERN_C

#include "VidyoVirtualRendererParticipant.h"
#include "VidyoVideoFrame.h"

LMI_BEGIN_EXTERN_C

Declare_LmiMap(LmiUint, LmiBool)

#pragma mark - VidyoVirtualRenderer callbacks declaration

/**
{callback apigroup="connector,simple":
	{name: VidyoVirtualRendererOnParticipantAdded}
	{parent: VidyoVirtualRenderer}
	{description: This callback is invoked to report the participant that joined conference and provides its information.}
	{prototype: void (*VidyoVirtualRendererOnParticipantAdded)(VidyoVirtualRenderer* r, const VidyoVirtualRendererParticipant* participant, const LmiVoidPtr userData)}
	{parameter:
		{name: r}
		{description: The VidyoVirtualRenderer object.}
	}
	{parameter:
		{name: participant}
		{description: The structure that contains participant information needed for the renderer.}
	}
	{parameter:
		{name: userData}
		{description: User data.}
	}
}
*/
typedef void (*VidyoVirtualRendererOnParticipantAdded)(VidyoVirtualRenderer* r, const VidyoVirtualRendererParticipant* participant, const LmiVoidPtr userData);

/**
{callback apigroup="connector,simple":
	{name: VidyoVirtualRendererOnParticipantRemoved}
	{parent: VidyoVirtualRenderer}
	{description: This callback is invoked to report the participant id that left the conference.}
	{prototype: void (*VidyoVirtualRendererOnParticipantRemoved)(VidyoVirtualRenderer* r, const VidyoVirtualRendererParticipant* participant, const LmiVoidPtr userData)}
	{parameter:
		{name: r}
		{description: The VidyoVirtualRenderer object.}
	}
	{parameter:
		{name: participant}
		{description: The structure that contains participant information needed for the renderer.}
	}
	{parameter:
		{name: userData}
		{description: User data.}
	}
}
*/
typedef void (*VidyoVirtualRendererOnParticipantRemoved)(VidyoVirtualRenderer* r, const VidyoVirtualRendererParticipant* participant, const LmiVoidPtr userData);

/**
{callback apigroup="connector,simple":
	{name: VidyoVirtualRendererOnDynamicParticipantChanged}
	{parent: VidyoVirtualRenderer}
	{description: This callback is invoked to report that the list of dynamically selected participants in a conference has changed.}
	{prototype: void (*VidyoVirtualRendererOnDynamicParticipantChanged)(VidyoVirtualRenderer* r, const LmiVector(VidyoVirtualRendererParticipant)* selectedParticipants, const LmiVoidPtr userData)}
	{parameter:
		{name: r}
		{description: The VidyoVirtualRenderer object.}
	}
	{parameter:
		{name: selectedParticipants}
		{description: Ordered array of most recently selected participants in the conference.}
	}
	{parameter:
		{name: userData}
		{description: User data.}
	}
}
*/

typedef void (*VidyoVirtualRendererOnDynamicParticipantChanged)(VidyoVirtualRenderer* r, const LmiVector(VidyoVirtualRendererParticipant)* selectedParticipants, const LmiVoidPtr userData);

/**
{callback apigroup="connector,simple":
	{name: VidyoVirtualRendererOnLoudestParticipantChanged}
	{parent: VidyoVirtualRenderer}
	{description: This callback is invoked to report that an audio-only participant has gain or lost loudest speaker status.}
	{prototype: void (*VidyoVirtualRendererOnLoudestParticipantChanged)(VidyoVirtualRenderer* r, const VidyoVirtualRendererParticipant* participant, LmiBool audioOnly, const LmiVoidPtr userData)}
	{parameter:
		{name: r}
		{description: The VidyoVirtualRenderer object. }
	}
	{parameter:
		{name: participant}
		{description: The structure that contains participant information needed for the renderer.}
	}
	{parameter:
		{name: audioOnly}
		{description: Indicates whether this participant has video streams.}
	}
	{parameter:
		{name: userData}
		{description: User data.}
	}
}
*/
typedef void (*VidyoVirtualRendererOnLoudestParticipantChanged)(VidyoVirtualRenderer* r, const VidyoVirtualRendererParticipant* participant, LmiBool audioOnly, const LmiVoidPtr userData);

/**
{callback apigroup="connector,simple":
	{name: VidyoVirtualRendererOnAudioLevelChanged}
	{parent: VidyoVirtualRenderer}
	{description: This callback is invoked to report the audio level for specific participant.}
	{prototype: void (*VidyoVirtualRendererOnAudioLevelChanged)(VidyoVirtualRenderer* r, const VidyoVirtualRendererParticipant* participant, LmiInt energy, LmiBool isSpeech, const LmiVoidPtr userData)}
	{parameter:
		{name: r}
		{description: The VidyoVirtualRenderer object. }
	}
	{parameter:
		{name: participant}
		{description: The structure that contains participant information needed for the renderer.}
	}
	{parameter:
		{name: energy}
		{description: Audio energy.}
	}
	{parameter:
		{name: isSpeech}
		{description: Indicates whether speech is detected.}
	}
	{parameter:
		{name: userData}
		{description: User data.}
	}
}
*/
typedef void (*VidyoVirtualRendererOnAudioLevelChanged)(VidyoVirtualRenderer* r, const VidyoVirtualRendererParticipant* participant, LmiInt energy, LmiBool isSpeech, const LmiVoidPtr userData);

/**
{callback apigroup="connector,simple":
	{name: VidyoVirtualRendererOnStreamAdded}
	{parent: VidyoVirtualRenderer}
	{description: This callback is invoked to report the video stream information of video source that was added to the conference.}
	{prototype: void (*VidyoVirtualRendererOnStreamAdded)(VidyoVirtualRenderer* r, const VidyoVirtualRendererStream* stream, const LmiVoidPtr userData)}
	{parameter:
		{name: r}
		{description: The VidyoVirtualRenderer object.}
	}
	{parameter:
		{name: stream}
		{description: The video stream information.}
	}
	{parameter:
		{name: userData}
		{description: User data.}
	}
}
*/
typedef void (*VidyoVirtualRendererOnStreamAdded)(VidyoVirtualRenderer* r, const VidyoVirtualRendererStream* stream, const LmiVoidPtr userData);

/**
{callback apigroup="connector,simple":
	{name: VidyoVirtualRendererOnStreamRemoved}
	{parent: VidyoVirtualRenderer}
	{description: This callback is invoked to report the video stream was removed from the conference.}
	{prototype: void (*VidyoVirtualRendererOnStreamRemoved)(VidyoVirtualRenderer* r, const VidyoVirtualRendererStream* stream, const LmiVoidPtr userData)}
	{parameter:
		{name: r}
		{description: The VidyoVirtualRenderer object.}
	}
	{parameter:
		{name: stream}
		{description: The video stream information.}
	}
	{parameter:
		{name: userData}
		{description: User data.}
	}
}
*/
typedef void (*VidyoVirtualRendererOnStreamRemoved)(VidyoVirtualRenderer* r, const VidyoVirtualRendererStream* stream, const LmiVoidPtr userData);

/**
{callback apigroup="connector,simple":
	{name: VidyoVirtualRendererOnStreamFrameReceived}
	{parent: VidyoVirtualRenderer}
	{description: This callback is invoked to send the frame of a video stream to the application.}
	{prototype: void (*VidyoVirtualRendererOnStreamFrameReceived)(VidyoVirtualRenderer* r, const VidyoVirtualRendererStream* stream, const VidyoVideoFrame *videoFrame, const LmiVoidPtr userData)}
	{parameter:
		{name: r}
		{description: The VidyoVirtualRenderer object.}
	}
	{parameter:
		{name: stream}
		{description: The video stream information.}
	}
	{parameter:
		{name: videoFrame}
		{description: The video frame.}
	}
	{parameter:
		{name: userData}
		{description: User data.}
	}
}
*/
typedef void (*VidyoVirtualRendererOnStreamFrameReceived)(VidyoVirtualRenderer* r, const VidyoVirtualRendererStream* stream, const VidyoVideoFrame* videoFrame, const LmiVoidPtr userData);

/**
{callback apigroup="connector,simple":
    {name: VidyoVirtualRendererOnFECCCapabilitiesChanged}
    {parent: VidyoVirtualRenderer}
    {description: This Callback is triggered when there is change in camera control capabilities.}
    {prototype: void (*VidyoVirtualRendererOnFECCCapabilitiesChanged)(VidyoVirtualRenderer* r, const VidyoVirtualRendererStream* stream, const VidyoCameraControlCapabilities* caps, const LmiVoidPtr userData)}
    {parameter:
        {name: r}
        {description: The VidyoVirtualRenderer object.}
    }
    {parameter:
        {name: stream}
        {description: The video stream information.}
    }
    {parameter:
        {name: caps}
        {description: The camera control capability.}
    }
    {parameter:
        {name: userData}
        {description: User data.}
    }
}
*/
typedef void (*VidyoVirtualRendererOnFECCCapabilitiesChanged)(VidyoVirtualRenderer* r, const VidyoVirtualRendererStream* stream, const VidyoCameraControlCapabilities* caps, const LmiVoidPtr userData);

#pragma mark - VidyoVirtualRenderer APIs declaration

/**
{function apigroup="connector,simple":
	{name: VidyoVirtualRendererConstruct}
	{parent: VidyoVirtualRenderer}
	{description: Constructs a virtual renderer.}
	{prototype: VidyoVirtualRenderer* VidyoVirtualRendererConstruct(VidyoVirtualRenderer* r, const LmiString *id, const LmiString *name, LmiAllocator* alloc)}
	{parameter:
		{name: r}
		{description: The VidyoVirtualRenderer object. }
	}
	{parameter:
		{name: id}
		{description: Unique ID.}
	}
	{parameter:
		{name: name}
		{description: Name of the virtual renderer.}
	}
	{parameter:
		{name: alloc}
		{description: The LmiAllocator object.}
	}
	{return: Returns a pointer to a constructed object on success, or NULL on failure.}
}
*/

VidyoVirtualRenderer* VidyoVirtualRendererConstruct(VidyoVirtualRenderer* r, const LmiString *id, const LmiString *name, LmiAllocator *alloc);

/**
{function apigroup="connector,simple":
	{name: VidyoVirtualRendererConstructCopy}
	{parent: VidyoVirtualRenderer}
	{description: Constructs a VidyoVirtualRenderer object as a copy of another.}
	{prototype: VidyoVirtualRenderer *VidyoVirtualRendererConstructCopy(VidyoVirtualRenderer *obj, const VidyoVirtualRenderer *other)}
	{parameter:
		{name: obj}
		{description: The VidyoVirtualRenderer object to construct.}
	}
	{parameter:
		{name: other}
		{description: The call object to make a copy of.}
	}
	{return: A pointer to a constructed object on success, or NULL on failure.}
}
*/

/**
{function apigroup="connector,simple":
	{name: VidyoVirtualRendererDestruct}
	{parent: VidyoVirtualRenderer}
	{description: Destructs an VidyoVirtualRenderer object.}
	{prototype: void VidyoVirtualRendererDestruct(VidyoVirtualRenderer *obj)}
	{parameter:
		{name: obj}
		{description: The VidyoVirtualRenderer object to destruct.}
	}
}
*/

/**
{function apigroup="connector,simple":
	{name: VidyoVirtualRendererAssign}
	{parent: VidyoVirtualRenderer}
	{description: Assigns one VidyoVirtualRenderer object the value of another. }
	{prototype: VidyoVirtualRenderer *VidyoVirtualRendererAssign(VidyoVirtualRenderer *obj, const VidyoVirtualRenderer *other)}
	{parameter:
		{name: obj}
		{description: The VidyoVirtualRenderer object.}
	}
	{parameter:
		{name: other}
		{description: The call object to make a copy of.}
	}
	{return: A pointer to the destination object on success, or NULL on failure.}
}
*/

/**
{function visibility="private":
	{name: VidyoVirtualRendererGetUserData}
	{parent: VidyoVirtualRenderer}
	{description: Gets user data.}
	{prototype: LmiVoidPtr VidyoVirtualRendererGetUserData(const VidyoVirtualRenderer* r)}
	{parameter:
		{name: r}
		{description: The VidyoVirtualRenderer object. }
	}
	{return: User data.}
}
*/
LmiVoidPtr VidyoVirtualRendererGetUserData(const VidyoVirtualRenderer* r);

/**
{function visibility="private":
	{name: VidyoVirtualRendererSetUserData}
	{parent: VidyoVirtualRenderer}
	{description: Sets user data.}
	{prototype: void VidyoVirtualRendererSetUserData(VidyoVirtualRenderer* r, LmiVoidPtr userData)}
	{parameter:
		{name: r}
		{description: The VidyoVirtualRenderer object. }
	}
	{parameter:
		{name: userData}
		{description: The User data. }
	}
}
*/
void VidyoVirtualRendererSetUserData(VidyoVirtualRenderer* r, LmiVoidPtr userData);

/**
{function apigroup="connector,simple":
	{name: VidyoVirtualRendererGetName}
	{parent: VidyoVirtualRenderer}
	{description: Gets the name of the virtual renderer.}
	{prototype: const LmiString* VidyoVirtualRendererGetName(const VidyoVirtualRenderer* r)}
	{parameter:
		{name: r}
		{description: The VidyoVirtualRenderer object. }
	}
	{return: Name of the virtual renderer.}
}
*/
const LmiString* VidyoVirtualRendererGetName(const VidyoVirtualRenderer* s);

/**
{function apigroup="connector,simple":
	{name: VidyoVirtualRendererGetId}
	{parent: VidyoVirtualRenderer}
	{description: Gets the id of the virtual renderer.}
	{prototype: const LmiString* VidyoVirtualRendererGetId(const VidyoVirtualRenderer* r)}
	{parameter:
		{name: r}
		{description: The VidyoVirtualRenderer object. }
	}
	{return: Id of the virtual renderer.}
}
*/
const LmiString* VidyoVirtualRendererGetId(const VidyoVirtualRenderer* r);

/**
{function apigroup="connector,simple":
	{name: VidyoVirtualRendererRegisterParticipantsEventListener}
	{parent: VidyoVirtualRenderer}
	{description: Registers virtual renderer callbacks to receive notifications about participants.}
	{prototype: LmiUint64 VidyoVirtualRendererRegisterParticipantsEventListener(VidyoVirtualRenderer* r, LmiVoidPtr userData, VidyoVirtualRendererOnParticipantAdded onParticipantAdded, VidyoVirtualRendererOnParticipantRemoved onParticipantRemoved, VidyoVirtualRendererOnLoudestParticipantChanged onLoudestParticipantChanged, VidyoVirtualRendererOnDynamicParticipantChanged onDynamicParticipantChanged, VidyoVirtualRendererOnAudioLevelChanged onAudioLevelChanged)}
	{parameter:
		{name: r}
		{description: The VidyoVirtualRenderer object. }
	}
	{parameter:
		{name: userData}
		{description: The user data, returned in callback.}
	}
	{parameter:
		{name: onParticipantAdded}
		{description: Notifies the application that the participant added and sends its information.}
	}
	{parameter:
		{name: onParticipantRemoved}
		{description: Notifies the application that the participant removed.}
	}
	{parameter:
		{name: onLoudestParticipantChanged}
		{description: Notifies the application that the loudest speaker was changed.}
	}
	{parameter:
		{name: onDynamicParticipantChanged}
		{description: Reports the list of new dynamic participants.}
	}
	{parameter:
		{name: onAudioLevelChanged}
		{description: Notifies the application the audio level of participant was changed.}
	}
	{return: Token for callbacks that used later to unregister callbacks.}
}
*/
LmiUint64 VidyoVirtualRendererRegisterParticipantsEventListener(VidyoVirtualRenderer* r, LmiVoidPtr userData, VidyoVirtualRendererOnParticipantAdded onParticipantAdded, VidyoVirtualRendererOnParticipantRemoved onParticipantRemoved, VidyoVirtualRendererOnLoudestParticipantChanged onLoudestParticipantChanged, VidyoVirtualRendererOnDynamicParticipantChanged onDynamicParticipantChanged, VidyoVirtualRendererOnAudioLevelChanged onAudioLevelChanged);

/**
{function apigroup="connector,simple":
	{name: VidyoVirtualRendererRegisterStreamsEventListener}
	{parent: VidyoVirtualRenderer}
	{description: Registers virtual renderer callbacks to receive notifications about streams.}
	{prototype: LmiUint64 VidyoVirtualRendererRegisterStreamsEventListener(VidyoVirtualRenderer* r, const LmiVoidPtr userData, VidyoVirtualRendererOnStreamAdded onStreamAdded, VidyoVirtualRendererOnStreamRemoved onStreamRemoved, VidyoVirtualRendererOnStreamFrameReceived onStreamsFrame, VidyoVirtualRendererOnFECCCapabilitiesChanged onFECCCapabilitiesChanged)}
	{parameter:
		{name: r}
		{description: The VidyoVirtualRenderer object. }
	}
	{parameter:
		{name: userData}
		{description: The user data, returned in callback.}
	}
	{parameter:
		{name: onStreamAdded}
		{description: Notifies the application that the stream added and sends its information.}
	}
	{parameter:
		{name: onStreamRemoved}
		{description: Notifies the application that the stream removed.}
	}
	{parameter:
		{name: onStreamsFrame}
		{description: Notifies the application that the video frame received for stream.}
	}
    {parameter:
        {name: onFECCCapabilitiesChanged}
        {description: Notifies the application about the camera control capabilities.}
    }
	{return: Token for callbacks that used later to unregister callbacks.}
}
*/
LmiUint64 VidyoVirtualRendererRegisterStreamsEventListener(VidyoVirtualRenderer* r, const LmiVoidPtr userData, VidyoVirtualRendererOnStreamAdded onStreamAdded, VidyoVirtualRendererOnStreamRemoved onStreamRemoved, VidyoVirtualRendererOnStreamFrameReceived onStreamsFrame, VidyoVirtualRendererOnFECCCapabilitiesChanged onFECCCapabilitiesChanged);

/**
{function apigroup="connector,simple":
	{name: VidyoVirtualRendererUnregisterEventListener}
	{parent: VidyoVirtualRenderer}
	{description: Unregisters virtual renderer callbacks to receive notifications about participants and streams.}
	{prototype: LmiVoidPtr VidyoVirtualRendererUnregisterEventListener(VidyoVirtualRenderer* r, LmiUint64 token)}
	{parameter:
		{name: r}
		{description: The VidyoVirtualRenderer object. }
	}
	{parameter:
		{name: token}
		{description: Token for callbacks that should be unregister.}
	}
    {return: The user data, passed in register function.}
}
*/
LmiVoidPtr VidyoVirtualRendererUnregisterEventListener(VidyoVirtualRenderer* r, LmiUint64 token);

/**
{function apigroup="connector,simple":
	{name: VidyoVirtualRendererStreamStart}
	{parent: VidyoVirtualRenderer}
	{description: Requests frames for the specific stream with specified parameters or updates stream parameters if frames have already been requested. Parameters are used to request the most suitable video stream for this source. It is set based on tile size..}
	{prototype: LmiBool VidyoVirtualRendererStreamStart(VidyoVirtualRenderer* r, LmiUint64 streamId, LmiUint width, LmiUint height, LmiTime frameInterval, LmiBool pin)}
	{parameter:
		{name: r}
		{description: The VidyoVirtualRenderer object. }
	}
	{parameter:
		{name: streamId}
		{description: The unique ID of stream.}
	}
	{parameter:
		{name: width}
		{description: Desired stream width.}
	}
	{parameter:
		{name: height}
		{description: Desired stream height.}
	}
	{parameter:
		{name: frameInterval}
		{description: Desired stream frame interval.}
	}
	{parameter:
		{name: pin}
		{description: LMI_TRUE to pin stream to always receive the video frames. LMI_FALSE to make the stream behavior default.}
	}
	{return: LMI_TRUE on success, LMI_FALSE otherwise.}
}
*/
LmiBool VidyoVirtualRendererStreamStart(VidyoVirtualRenderer* r, LmiUint64 streamId, LmiUint width, LmiUint height, LmiTime frameInterval, LmiBool pin);

/**
{function apigroup="connector,simple":
	{name: VidyoVirtualRendererStreamStop}
	{parent: VidyoVirtualRenderer}
	{description: Stops receiving frames for a specific stream.}
	{prototype: void VidyoVirtualRendererStreamStop(VidyoVirtualRenderer* r, LmiUint64 streamId)}
	{parameter:
		{name: r}
		{description: The VidyoVirtualRenderer object. }
	}
	{parameter:
		{name: streamId}
		{description: The unique ID of stream.}
	}
}
*/
void VidyoVirtualRendererStreamStop(VidyoVirtualRenderer* r, LmiUint64 streamId);

/**
{function apigroup="connector,simple":
    {name: VidyoVirtualRendererSendFECCCommands}
    {parent: VidyoVirtualRenderer}
    {description: Sends the camera control commands.}
    {prototype: LmiBool VidyoVirtualRendererSendFECCCommands(VidyoVirtualRenderer* r, LmiUint64 streamId, LmiVector(VidyoCameraControlCommand)* cmds)}
    {parameter:
        {name: r}
        {description: The VidyoVirtualRenderer object.}
    }
    {parameter:
        {name: streamId}
        {description: The unique ID of stream.}
    }
    {parameter:
        {name: cmds}
        {description: Camera control commands.}
    }
    {return: LMI_TRUE on success, LMI_FALSE otherwise.}
}
*/
LmiBool VidyoVirtualRendererSendFECCCommands(VidyoVirtualRenderer* r, LmiUint64 streamId, LmiVector(VidyoCameraControlCommand)* cmds);

LMI_END_EXTERN_C

#if LMI_INLINE_NEED_HEADER_FILE_DEFINITIONS
#include "VidyoVirtualRendererInline.h"
#endif

#endif /* VIDYO_VIRTUAL_RENDERER_H */
