# ![Vidyo](http://www.vidyo.com/images/logo.png) 1. [Overview](#Overview) 2. [Getting Started](#GettingStarted) 3. [Initializing](#Initializing) 4. [LogingIn](#LogingIn) 5. [Concepts](#Concepts) 6. [Participants](#Participants) 7. [Device Management](#DeviceManagement) 8. [Sharing](#Sharing) 9. [Layout](#Layout) <a name="Overview"></a> ## Overview Vidyo's connector library enables the developer to add real-time communication capabilities to their applications using a simple API that spans multiple platforms (Windows/Mac/Linux/iOS/Android) and languages (C/Objective-C/Java/JavaScript). <a name="GettingStarted"></a> ## Getting Started There are many possible ways to use the library depending on the application requirements. #### Mac Desktop application Use the platform specific library for Mac(Windows/Mac/Linux) and interface using C/C# binding. Widnows SDK: https://static.vidyo.io/latest/package/VidyoClient-WindowsSDK.zip MacOS SDK: https://static.vidyo.io/latest/package/VidyoClient-OSXSDK.zip #### Web Browser application with Plugin Use our NPAPI plugin and interface using our JavaScript binding (VidyoClient.js) SDK: https://static.vidyo.io/latest/package/VidyoClient-WebSDK.zip #### Web Browser application without Plugin Use our Native Web-RTC version of VidyoClient.js and interface using our JavaScript binding. SDK: https://static.vidyo.io/latest/package/VidyoClient-WebSDK.zip #### iOS application Use our iOS library and interface using Objective-C binding. SDK: https://static.vidyo.io/latest/package/VidyoClient-iOSSDK.zip #### Android Application Use our Android library and interface using Java binding. SDK: https://static.vidyo.io/latest/package/VidyoClient-AndroidSDK.zip Once you load our library by adding it to your project or installing the NPAPI plugin, you can call VidyoClient funcitons. <a name="LogingIn"></a> ## Logging In DeveloperKey and ApplicationID are unique for each developer and are used to gain access to the vidyo.io platform 1. Retrieve the **DeveloperKey** from the Vidyo.io site 2. Generate a **Token** from the developer key 3. Use the **Token** to connect to a room in (#Concepts) ### Developer Key A DeveloperKey is a shared secret between Vidyo.io and the developer's backend application. It is used to generate access tokens on the customer backend and should never be sent to the endpoint itself. Access to the Developer Key should be restricted since every token that is signed by it will be used for access and billing. ### ApplicationID ApplicationID identifies the developer to our platform. The developer can automatically provision any user such as user1@ApplicationID to our system when generating the token. ### Token Token is a signed user metadata with the DeveloperKey that is sent to the endpoint in order to login. When the developer's backend application wants to give the endpoint access, it will sign the user1@ApplicationID, expiration date, vcard (optional) with the DeveloperKey. ### vCard vCards provide optional information about the user. Currently ignored by the vidyo.io platform. ```python <vCard xmlns='vcard-temp'><FN>First Name</FN><NICKNAME>nickname</NICKNAME></vCard> ``` ### Format ```python 'provision' \0 <BARE_JID> \0 <EXPIRES_AT> \0 <VCARD> \0 <MAC> ``` ### Example ```python 'provision' \0 user1@A1B2C3 \0 64875466458 \0 <vCard></vCard> \0 86cd344c98b345390c1961e12cd4005659b4b0b3c7ec475bde9acc9d47eec27e8ddc67003696af582747fb52e578a715 ``` The resulting string is converted to binary and signed using an HMAC with SHA-2 family function SHA-384. ### Samples Python sample generator: https://static.vidyo.io/latest/utils/generateToken.py ```sh python3 generateToken.py --key=rUlaMASgt1Byi4Kp3sKYDeQzo --appID=ApplicationID --userName=user1 --vCardFile vcard-example.xml --expiresInSecs=10000 ``` Java sample generator: https://static.vidyo.io/latest/utils/generateToken.jar ```sh java -jar generate-token.jar <key> <appID> <userName> <vCardFile> <expiresInSeconds> ``` <a name="Initializing"></a> ## Initializing The first step is to initialize the VidyoConnector ```javascript /* JavaScript Example: */ /* Load the VidyoClient.js script and pass the onVidyoClientLoaded callback as an onload parameter */ <script src="https://static.vidyo.io/latest/javascript/VidyoClient/VidyoClient.js?onload=onVidyoClientLoaded"></script> /* When the library loads the callback will be invoked */ <script type="text/javascript"> function onVidyoClientLoaded(status) { switch (status.state) { case "READY": // The library is operating normally // After the VidyoClient is successfully initialized a global VC object will become available // Load the rest of the application break; case "RETRYING": // The library operating is temporarily paused break; case "FAILED": // The library operating has stopped break; case "NOTAVAILABLE": // The library is not available break; } } </script> ``` ```C /* C Example: */ /* Initialize client library */ VidyoClientInitialize(); ``` <a name="Concepts"></a> ## Concepts VidyoConnector is a very simple API that only requires two steps: 1. **Construct** and pass the window where you want preview and participants rendered. 2. **Connect** to the live conference. You can choose the **userId** that represents the user in your application and the **resourceId** where you want all the live participants to connect. ```javascript /* JavaScript Example: */ /* Assume that your DOM has a div with id="renderer" where you want the preview and the live conference rendered */ /* After the VidyoClient is successfully initialized a global VC object will become available */ VC.CreateVidyoConnector({ viewId: "renderer", // Div ID where the composited video will be rendered, see VidyoConnectorSample.html viewStyle: "VIDYO_CONNECTORVIEWSTYLE_Default", // Visual style of the composited renderer remoteParticipants: 16, // Maximum number of participants logFileFilter: "warning all@VidyoConnector info@VidyoClient", }).then(function(vidyoConnector) { vidyoConnector.Connect({ // Define handlers for connection events. onSuccess: function() {/* Connected */}, onFailure: function(reason) {/* Failed */}, onDisconnected: function(reason) {/* Disconnected */} }).then(function(status) { if (status) { console.log("ConnectCall Success"); } else { console.error("ConnectCall Failed"); } }).catch(function() { console.error("ConnectCall Failed"); }); }).catch(function() { console.error("CreateVidyoConnector Failed"); }); ``` ```C /* C Example: */ void VidyoConnectorOnSuccessCallback(VidyoConnector* c) { /* Connected */ } void VidyoConnectorOnFailureCallback(VidyoConnector* c, VidyoConnectorFailReason reason) { /* Failed */ } void VidyoConnectorOnDisconnectedCallback(VidyoConnector* c, VidyoConnectorDisconnectReason reason) { /* Disconnected */ } /* Pass in the view, dimensions and the position within the view where the conference should be rendered */ void ConnectToResource(LmiViewId* viewId, LmiInt x, LmiInt y, LmiUint width, LmiUint height, const char* host, const char* token, const char* displayName, const char *resourceId) { VidyoConnector c; LmiUint remoteParticipants = 16; /* Maximum number of remote participants to show */ VidyoConnectorConstruct(&c, viewId, VIDYO_CONNECTORVIEWSTYLE_Default, remoteParticipants, "warning all@VidyoConnector info@VidyoClient", NULL, NULL); VidyoConnectorSetViewPosition(&c, viewId, x, y, width, height); VidyoConnectorConnect(&c, host, token, displayName, resourceId, VidyoConnectorOnSuccessCallback, VidyoConnectorOnFailureCallback, VidyoConnectorOnDisconnectedCallback); } ``` <a name="Participants"></a> ## Participants VidyoParticipant represents the other users. Once you are connected, the **OnParticipant** can be triggered for every current participant and every time a new participant enters and leaves. ```javascript /* JavaScript Example: */ vidyoConnector.RegisterParticipantEventListener( { onJoined: function(participant), { /* Participant Joined */}, onLeft: function(participant), { /* Participant Left */}, onDynamicChanged: function(participants), { /* Ordered array of participants according to rank */ }, onLoudestChanged: function(participant, audioOnly), { /* Current loudest speaker */ }, onChatMessageReceived: function(message) { /* Message received from other participants */} }).then(function() { console.log("RegisterParticipantEventListener Success"); }).catch(function() { console.err("RegisterParticipantEventListener Failed"); }); ``` ```C /* C Example: */ void VidyoConnectorOnParticipantJoinedCallback(VidyoConnector* c, VidyoParticipant* participant) { /* Participant Joined */ } void VidyoConnectorOnParticipantLeftCallback(VidyoConnector* c, VidyoParticipant* participant) { /* Participant Left */ } void VidyoConnectorOnDynamicParticipantChanged(VidyoConnector* c, LmiVector(VidyoParticipant)* participants) { /* Ordered array of participants according to rank */ } void VidyoConnectorOnLoudestParticipantChanged)(VidyoConnector* c, const VidyoParticipant* participant, LmiBool audioOnly) { /* Current loudest speaker */ } void VidyoConnectorOnChatMessageReceivedCallback(VidyoConnector* c, VidyoParticipant* participant, VidyoChatMessage* chatMessage) { /* Message received from other participants */} /* Register Participant Callbacks*/ VidyoConnectorOnParticipant(&c, VidyoConnectorOnParticipantJoinedCallback, VidyoConnectorOnParticipantLeftCallback, VidyoConnectorOnDynamicParticipantChanged, VidyoConnectorOnLoudestParticipantChanged, VidyoConnectorOnChatMessageReceivedCallback); ``` <a name="DeviceManagement"></a> ## Device Management If no device management API's are called, the VidyoConnector will pick the default camera/microphone/speaker available on your system, but if you wish to override that behaviour there are two ways of manipulating devices. ### Cycle You can Cycle your camera/microphone/speaker until you find the right one: ```javascript /* JavaScript Example: */ vidyoConnector.CycleCamera(); vidyoConnector.CycleMicrohpone(); vidyoConnector.CycleSpeaker(); ``` ```C /* C Example: */ VidyoConnectorCycleCamera(); VidyoConnectorCycleMicrohpone(); VidyoConnectorCycleSpeaker(); ``` ### Resetting to default If at any time you wish to reset devices back to default you can use the **SelectDefaultCamera/SelectDefaultMicrophone/SelectDefaultSpeaker** API. ```javascript /* JavaScript Example: */ vidyoConnector.SelectDefaultCamera(); vidyoConnector.SelectDefaultMicrophone(); vidyoConnector.SelectDefaultSpeaker(); ``` ```C /* C Example: */ VidyoConnectorSelectDefaultCamera(); VidyoConnectorSelectDefaultMicrophone(); VidyoConnectorSelectDefaultSpeaker(); ``` ### Selecting devices If you wish to select devices by name and would like to be notified which devices are selected you can use the **SelectCamera/SelectMicrophone/SelectSpeaker** and **OnCamera/OnMicrophone/OnSpeaker** API. ```javascript /* JavaScript Example: */ vidyoConnector.RegisterLocalCameraEventListener( { onAdded: function(camera) { /* New camera is available */ if (/* This is the camera you want */) { vidyoConnector.SelectCamera(camera); } }, onRemoved: function(camera) { /* Existing camera became unavailable */ }, onSelected: function(camera) { /* Camera was selected by you or automatically */ } }).then(function() { console.log("RegisterLocalCameraEventListener Success"); }).catch(function() { console.error("RegisterLocalCameraEventListener Failed"); }); vidyoConnector.RegisterLocalMicrophoneEventListener( { onAdded: function(microphone) { /* New microphone is available */ if (/* This is the microphone you want */) { vidyoConnector.SelectMicrophone(microphone); } }, onRemoved: function(microphone) { /* Existing microphone became unavailable */ }, onSelected: function(microphone) { /* Microphone was selected by you or automatically */ } }).then(function() { console.log("RegisterLocalMicrophoneEventListener Success"); }).catch(function() { console.error("RegisterLocalMicrophoneEventListener Failed"); }); vidyoConnector.RegisterLocalSpeakerEventListener( { onAdded: function(speaker) { /* New speaker is available */ if (/* This is the speaker you want */) { vidyoConnector.SelectSpeaker(speaker); } }, onRemoved: function(speaker) { /* Existing speaker became unavailable */ }, onSelected: function(speaker) { /* Speaker was selected by you or automatically */ } }).then(function() { console.log("RegisterLocalSpeakerEventListener Success"); }).catch(function() { console.error("RegisterLocalSpeakerEventListener Failed"); }); ``` ```C /* C Example: */ void VidyoConnectorOnLocalCameraAddedCallback(VidyoConnector* c, VidyoLocalCamera* camera) { /* New camera is available */ if (/* This is the camera you want */) { VidyoConnectorSelectLocalCamera(c, camera); } } void VidyoConnectorOnLocalCameraRemovedCallback(VidyoConnector* c, VidyoLocalCamera* camera) { /* Existing camera became unavailable */ } void VidyoConnectorOnLocalCameraSelectedCallback(VidyoConnector* c, VidyoLocalCamera* camera) { /* Camera was selected by you or automatically */ } void VidyoConnectorOnLocalMicrophoneAddedCallback(VidyoConnector* c, VidyoLocalMicrophone* microphone) { /* New microphone is available */ if (/* This is the microphone you want */) { VidyoConnectorSelectLocalMicrophone(c, microphone); } } void VidyoConnectorOnLocalMicrophoneRemovedCallback(VidyoConnector* c, VidyoLocalMicrophone* microphone) { /* Existing microphone became unavailable */ } void VidyoConnectorOnLocalMicrophoneSelectedCallback(VidyoConnector* c, VidyoLocalMicrophone* microphone) { /* Microphone was selected by you or automatically */ } void VidyoConnectorOnLocalSpeakerAddedCallback(VidyoConnector* c, VidyoLocalSpeaker* speaker) { /* New speaker is available */ if (/* This is the speaker you want */) { VidyoConnectorSelectLocalSpeaker(c, speaker); } } void VidyoConnectorOnLocalSpeakerRemovedCallback(VidyoConnector* c, VidyoLocalSpeaker* speaker) { /* Existing speaker became unavailable */ } void VidyoConnectorOnLocalSpeakerSelectedCallback(VidyoConnector* c, VidyoLocalSpeaker* speaker) { /* Speaker was selected by you or automatically */ } /* Register Device callbacks */ VidyoConnectorRegisterLocalCameraEventListener(&c, VidyoConnectorOnLocalCameraAddedCallback, VidyoConnectorOnLocalCameraRemovedCallback, VidyoConnectorOnLocalCameraSelectedCallback); VidyoConnectorRegisterLocalMicrophoneEventListener(&vc, VidyoConnectorOnLocalMicrophoneAddedCallback, VidyoConnectorOnLocalMicrophoneRemovedCallback, VidyoConnectorOnLocalMicrophoneSelectedCallback); VidyoConnectorRegisterLocalSpeakerEventListener(&vc, VidyoConnectorOnLocalSpeakerAddedCallback, VidyoConnectorOnLocalSpeakerRemovedCallback, VidyoConnectorOnLocalSpeakerSelectedCallback); ``` <a name="Sharing"></a> ## Sharing Windows and Monitors can be shared in a conferece. Passing null into **SelectWindow/SelectMonitor** will stop sharing. ```javascript /* JavaScript Example: */ vidyoConnector.RegisterLocalWindowShareEventListener( { onAdded: function(window) { /* New window is available for sharing*/ if (/* This is the window you want to share*/) { vidyoConnector.SelectWindow(window) } /* Get window Preview */ var dataUri = window.GetPreviewFrameDataUri(); }, onRemoved: function(window) { /* Existing window is no longer avaialbe for sharing */ }, onSelected: function(window) { /* Window was selected */ } }).then(function() { console.log("RegisterLocalWindowShareEventListener Success"); }).catch(function() { console.error("RegisterLocalWindowShareEventListener Failed"); }); vidyoConnector.RegisterLocalMonitorEventListener( { onAdded: function(monitor) { /* New monitor is available for sharing*/ if (/* This is the monitor you want to share*/) { vidyoConnector.SelectMonitor(monitor) } /* Get monitor Preview */ var dataUri = monitor.GetPreviewFrameDataUri(); }, onRemoved: function(monitor) { /* Existing monitor is no longer avaialbe for sharing */ }, onSelected: function(monitor) { /* Monitor was selected */ } }).then(function() { console.log("RegisterLocalMonitorEventListener Success"); }).catch(function() { console.error("RegisterLocalMonitorEventListener Failed"); }); ``` ```C /* C Example: */ void VidyoConnectorOnLocalWindowShareAddedCallback(VidyoConnector* c, VidyoLocalWindowShare* window) { /* New window is available */ if (/* This is the window you want */) { VidyoConnectorSelectLocalWindowShare(c, window); } } void VidyoConnectorOnLocalWindowShareRemovedCallback(VidyoConnector* c, VidyoLocalWindowShare* window) { /* Existing window became unavailable */ } void VidyoConnectorOnLocalWindowShareSelectedCallback(VidyoConnector* c, VidyoLocalWindowShare* window) { /* window was selected by you or automatically */ } void VidyoConnectorOnLocalMonitorAddedCallback(VidyoConnector* c, VidyoLocalMonitor* monitor) { /* New monitor is available */ if (/* This is the monitor you want */) { VidyoConnectorSelectLocalMonitor(c, monitor); } } void VidyoConnectorOnLocalMonitorRemovedCallback(VidyoConnector* c, VidyoLocalMonitor* monitor) { /* Existing monitor became unavailable */ } void VidyoConnectorOnLocalMonitorSelectedCallback(VidyoConnector* c, VidyoLocalMonitor* monitor) { /* monitor was selected by you or automatically */ } /* Register Device callbacks */ VidyoConnectorRegisterLocalWindowShareEventListener(&c, VidyoConnectorOnLocalWindowShareAddedCallback, VidyoConnectorOnLocalWindowShareRemovedCallback, VidyoConnectorOnLocalWindowShareSelectedCallback); VidyoConnectorRegisterLocalMonitorEventListener(&vc, VidyoConnectorOnLocalMonitorAddedCallback, VidyoConnectorOnLocalMonitorRemovedCallback, VidyoConnectorOnLocalMonitorSelectedCallback); ``` <a name="Layout"></a> ## Layout VidyoConnector proivdes a default compositing renderer in the viewId that was passed in when connector was created. However, if you wish to render sources into separate winow and maintain a custom layout you can use the **ShowSourceInView** API. ```javascript /* JavaScript Example: */ /* custom local preview */ vidyoConnector.RegisterLocalCameraEventListener( { onAdded: function(camera) { /* New camera is available */ if (/* This is the camera you want to view */) { vidyoConnector.ShowLocalCameraInView( { viewId: "Div where camera should be renderered", camera: camera, displayCropped: true, allowZoom: false }); } }, onRemoved: function(camera) { /* Existing camera became unavailable */ if (/* This is the camera that was viewed earlier */) { vidyoConnector.HideView( { viewId: "Div where camera should be renderered" }); } }, onSelected: function(camera) { /* Camera was selected by you or automatically */ } }).then(function() { console.log("RegisterLocalCameraEventListener Success"); }).catch(function() { console.error("RegisterLocalCameraEventListener Failed"); }); /* custom participant's source view */ vidyoConnector.RegisterRemoteCameraEventListener( { onAdded: function(participant, camera) { /* New camera is available */ if (/* This is the camera you want to view */) { vidyoConnector.ShowRemoteCameraInView( { viewId: "Div where camera should be renderered", camera: camera, displayCropped: true, allowZoom: false }); } }, onRemoved: function(participant, camera) { /* Existing camera became unavailable */ if (/* This is the camera that was viewed earlier */) { vidyoConnector.HideView( { viewId: "Div where camera should be renderered" }); } } }).then(function() { console.log("RegisterRemoteCameraEventListener Success"); }).catch(function() { console.error("RegisterRemoteCameraEventListener Failed"); }); ``` ```C /* C Example: */ void ShowPreview(VidyoConnector *c, LmiViewId* viewId, LmiInt x, LmiInt y, LmiUint width, LmiUint height, VidyoLocalCamera *camera, LmiBool displayCropped, LmiBool allowZoom) { VidyoConnectorShowLocalCameraInView(c, viewId, camera, displayCropped, allowZoom); VidyoConnectorSetViewPosition(c, viewId, x, y, width, height); } void ShowParticipantSource(VidyoConnector* c, LmiViewId* viewId, LmiInt x, LmiInt y, LmiUint width, LmiUint height, VidyoRemoteCamera* camera, LmiBool isStatic, LmiBool displayCropped, LmiBool allowZoom) { VidyoConnectorShowRemoteCameraInView(c, viewId, camera, isStatic, displayCropped, allowZoom); VidyoConnectorSetViewPosition(c, viewId, x, y, width, height); } ```